I know how to do it. I a just wondering what people feel would be a good interface (in the spirit of the PARTITION/SPLIT-SEQUENCE and EXTREMIZE debate).
I often find myself doing things like
(loop for i from 0 to N collect (make-something))
just because
(make-list N :initial-element (make-something))
fills the list with EQ elements. (The same applies to MAKE-ARRAY, of course).
I was thinking to write something along the lines of
(defun make-list-collecting (n &key (element-constructor (lambda () nil))) (loop for i from 0 below N collect (funcall f)))
(of course this could - and maybe should - be generalized to various sequences and arrays).
What does the "vox populi" say?
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
In article <y6c66cssvad....@octagon.mrl.nyu.edu>, Marco Antoniotti <marc...@cs.nyu.edu> wrote:
>I know how to do it. I a just wondering what people feel would be a >good interface (in the spirit of the PARTITION/SPLIT-SEQUENCE and >EXTREMIZE debate).
>I often find myself doing things like
> (loop for i from 0 to N collect (make-something))
>just because
> (make-list N :initial-element (make-something))
>fills the list with EQ elements. (The same applies to MAKE-ARRAY, of >course).
I wonder why you do this so much? It seems to me that most of the time when I've wanted to initialize a sequence by doing a computation, the indices frequently apply. E.g. something like:
(loop for i below n collect (* i 2))
If they're not a function of the index, they're usually a function of something that will be discovered later, so I let the elements default to NIL (or unspecified, in the case of an array) and fill them in later.
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <bar...@genuity.net> writes: > In article <y6c66cssvad....@octagon.mrl.nyu.edu>, > Marco Antoniotti <marc...@cs.nyu.edu> wrote: > >I know how to do it. I a just wondering what people feel would be a > >good interface (in the spirit of the PARTITION/SPLIT-SEQUENCE and > >EXTREMIZE debate).
> >I often find myself doing things like
> > (loop for i from 0 to N collect (make-something))
> >just because
> > (make-list N :initial-element (make-something))
> >fills the list with EQ elements. (The same applies to MAKE-ARRAY, of > >course).
> I wonder why you do this so much? It seems to me that most of the time > when I've wanted to initialize a sequence by doing a computation, the > indices frequently apply. E.g. something like:
> (loop for i below n collect (* i 2))
> If they're not a function of the index, they're usually a function of > something that will be discovered later, so I let the elements default to > NIL (or unspecified, in the case of an array) and fill them in later.
You are forgetting copier functions. Sometimes I find it better to allocate a vector of (different) objects and then modify them appropriately.
Moreover, if you initialize a vector with NIL elements, you will have to declare it as
(vector (or null <your-type>))
I find this cluttering. If possible I'd like to always declare
(vector <your-type>)
Of course it isn't something I need to die over. I can always trade off.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
In article <y6c3d7wslv7....@octagon.mrl.nyu.edu>, Marco Antoniotti <marc...@cs.nyu.edu> wrote:
>Moreover, if you initialize a vector with NIL elements, you will have >to declare it as
> (vector (or null <your-type>))
That's why I said to let them default, rather than initializing them explicitly to anything.
But I admit that I've never bothered with such declarations in the first place. The only array element type declarations that I've ever found useful were the ones that affected the array representation; typically these are element types like FIXNUM, SHORT-FLOAT, BIT, and CHARACTER.
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <bar...@genuity.net> writes: > In article <y6c3d7wslv7....@octagon.mrl.nyu.edu>, > Marco Antoniotti <marc...@cs.nyu.edu> wrote: > >Moreover, if you initialize a vector with NIL elements, you will have > >to declare it as
> > (vector (or null <your-type>))
> That's why I said to let them default, rather than initializing them > explicitly to anything.
Thanks. I learned something. :-) Here's how it happened.
First, I was wondering if there is a difference between initializing array elements and letting them default: in (let ((x nil) y)), there is no such difference. However, CLHS says that if I make an array with (make-array 5 :element-type <my-type>), then I'm not allowed to read elements I haven't initialized; thus MAKE-ARRAY doesn't have to initialize the array. This is surprising, but I suppose it saves time with large arrays.
(misguidedly
Is the resulting array then of type (vector <my-type>)? I guess it is, except some elements haven't been initialized and must not be read.
Am I allowed to (check-type <my-array> '(vector <my-type>))? If that has to read and check every element, including the uninitialized ones, then it is not allowed.
What if I assign the array to a variable whose type I've declared as (vector <my-type>), and the Lisp chooses to check the type of the array before letting the assignment succeed? That would be equivalent to the forbidden CHECK-TYPE. Can Lisp implementations then run automatic checks of that kind at all?)
However: CHECK-TYPE need not scan through the array, because it doesn't check the actual elements, but rather what kind of elements the array *could* contain, and that cannot change after the array has been created! Thus all the problems disappear.
I still find it odd that the parameters of type specifiers VECTOR and ARRAY work so differently from CONS, where the actual values in the car and the cdr are checked. Does this difference have a name? All these types are listed as "Compound Type Specifier Kind: Specializing."
>>>>> "Kalle" == Kalle Olavi Niemitalo <k...@iki.fi> writes:
Kalle> Barry Margolin <bar...@genuity.net> writes: >> In article <y6c3d7wslv7....@octagon.mrl.nyu.edu>, >> Marco Antoniotti <marc...@cs.nyu.edu> wrote: >> >Moreover, if you initialize a vector with NIL elements, you will have >> >to declare it as >> > >> > (vector (or null <your-type>)) >> >> That's why I said to let them default, rather than initializing them >> explicitly to anything.
Kalle> Thanks. I learned something. :-) Kalle> Here's how it happened.
Kalle> First, I was wondering if there is a difference between initializing Kalle> array elements and letting them default: in (let ((x nil) y)), there Kalle> is no such difference. However, CLHS says that if I make an array Kalle> with (make-array 5 :element-type <my-type>), then I'm not allowed to Kalle> read elements I haven't initialized; thus MAKE-ARRAY doesn't have to Kalle> initialize the array. This is surprising, but I suppose it saves time Kalle> with large arrays.
But practically speaking, it has to be initialized to something. If (upgraded-array-element-type <my-type>) => T, then the elements have to be initialized to something useful otherwise the potentially random elements would confuse the garbage collector.
Raymond Toy <t...@rtp.ericsson.se> writes: > But practically speaking, it has to be initialized to something. If > (upgraded-array-element-type <my-type>) => T, then the elements have > to be initialized to something useful otherwise the potentially random > elements would confuse the garbage collector.
The implementation could put a magic value in the first element, and then the second element would say how many uninitialized elements follow. This would satisfy the GC... but slow down SETF of AREF.
If Lisp implementations always initialize arrays whose upgraded element type is T, can I specify an initial value for free?
> > But practically speaking, it has to be initialized to something. If > > (upgraded-array-element-type <my-type>) => T, then the elements have > > to be initialized to something useful otherwise the potentially random > > elements would confuse the garbage collector.
> The implementation could put a magic value in the first element, and > then the second element would say how many uninitialized elements > follow. This would satisfy the GC... but slow down SETF of AREF.
> If Lisp implementations always initialize arrays whose upgraded > element type is T, can I specify an initial value for free?
No, because it may be that the host operating system offers you a way to get a block of data initialized to "something known to the vendor" but not "something agreed upon community-wide across vendors of Lisp". The vendor is free to implement their GC so as to take advantage of the "something known" even if the something known is something conceptually "dumb" as long as it's "gc-recognizable". For you to be able to substitute something might slow things down by requiring a user-level iteration across something the system was already going to have initialized.
This is, in effect, the price of "portabilty" in Lisp design. People talk about how C is touted as portable, but in practice Lisp is believed by many Lisp programmers to port better. I think the reason is situations like this where C would happily offer you a per-vendor spec of what the memory you grab will be initialized to and let you call it, even though it might vary by vendor. So when you port, you find places like this getting all kinds of little conditionals as we find that someone else initialized something differently so the setup of this page has to be different. There might be a place where Lisp is less efficient than C as a result, but at least Lisp will port on this point without you having to re-examine how memory is initialized. Bugs introduced by variances like this are subtle and can take forever to track down. Lisp spares you that as well.
Revel in it. Don't try to fight it... It's doing you a favor. Let it.
> > But practically speaking, it has to be initialized to something. If > > (upgraded-array-element-type <my-type>) => T, then the elements have > > to be initialized to something useful otherwise the potentially random > > elements would confuse the garbage collector.
> The implementation could put a magic value in the first element, and > then the second element would say how many uninitialized elements > follow. This would satisfy the GC... but slow down SETF of AREF.
I can't see any serious implementation doing any such thing. As you say, it would seriously slow down _every_ setf of aref even after such an array is all "fixed up", because the magic value would always have to be checked for.
> If Lisp implementations always initialize arrays whose upgraded > element type is T, can I specify an initial value for free?
In Allegro CL, at least, the answer is "yes" for heap-allocated arrays, and "no" for stack-allocated arrays. Stack-allocated arrays, even of type T, are allocated without initialization when no :initial-element argument is given, so they're fast. However, it is up to you to initialize them before you use them.
-- Duane Rettig Franz Inc. http://www.franz.com/ (www) 1995 University Ave Suite 275 Berkeley, CA 94704 Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)
> First, I was wondering if there is a difference between initializing > array elements and letting them default: in (let ((x nil) y)), there is > no such difference.
There is, but it does not matter, because the only rational thing to do is to initialize the variable to nil, and that is also specified. If, however, you declare a variable's type such that nil is not a possible value, you must, because the language does not _strongly_ support type declarations (such as by requiring that type violations be signaled as compile-time errors where possible to determine and warning about the inability to determine them where not), initialize the variable properly.
For instance, given the following function definition, do you expect (foo 0) to return nil or 0 or something else or do you expect it to signal an error?
Please note that this is _not_ safe code (in as many meanings as you can find of that term :), and that by asking for maximum performance and no safety, _I_ expect this to return whatever machine representation adding the machine word that represents the fixnum 0 to the machine word that represents nil, which in some cases might well return nil, unless the hardware has type bit checks, like the good old SPARC does.
In my opinion, it is important that variables are initialized before use, and I think that it should be an error if a variable can be determined to be referenced for its value before it is initialized. If it cannot be determined that it has been initialized before any given use, that should produce be a warning.
> However, CLHS says that if I make an array with (make-array 5 > :element-type <my-type>), then I'm not allowed to read elements I haven't > initialized; thus MAKE-ARRAY doesn't have to initialize the array. This > is surprising, but I suppose it saves time with large arrays.
Huh? You asked it not to be initialized. Why did you expect it to be? If you want something to be initialized, ask for it. I routinely ask make-array to initialize things for me unless the first thing I will do is to initialize it myself, in which case it would be time worth saving to avoid the double initialization.
> (misguidedly
> Is the resulting array then of type (vector <my-type>)? I guess it > is, except some elements haven't been initialized and must not be > read.
The vector and its elements have _separate_ types. Type theory and type practice are not quite compatible in many cases, because so much type theory is wrong. If type theory had dealt with typed data and not typed variables, so much more progress would have occured in this area. What theoretical foundation we have today is largely useless in a world where there is a universal supertype for all types, since they all assume a disjoint type space. I have never figured out why this is a smart thing to assume in a theoretical framework -- it seems downright stupid to me, and makes "object-oriented" programming so much harder to fit into it and describe. (I fault "modern" type theory for most of the disasters in "modern" programming language design. All of the wonderful things they want (such as static type checking and program validation) are just as hard and no harder to do in a dynamically typed than a statically typed value universe, and they prove themselves useless in a world where all "object-oriented" objects descend from some super-Object, too.) It also seems that your confusions stem from a type theoretical background that has failed to describe the real world and fit a _too_ simple mathematical model of whatever they thought they saw.
> Am I allowed to (check-type <my-array> '(vector <my-type>))? If that > has to read and check every element, including the uninitialized ones, > then it is not allowed.
When you query the type of the vector, you only query the type of the container. When you query the type of each element, you query the type of the contained. These are very different operations and concepts.
> However: CHECK-TYPE need not scan through the array, because it > doesn't check the actual elements, but rather what kind of elements > the array *could* contain, and that cannot change after the array has > been created! Thus all the problems disappear.
Not actually true, but close enough. See upgraded-array-element-type.
> I still find it odd that the parameters of type specifiers VECTOR and > ARRAY work so differently from CONS, where the actual values in the > car and the cdr are checked. Does this difference have a name? All > these types are listed as "Compound Type Specifier Kind: Specializing."
cons is a special case, just like complex. E.g., you can use the form (typep (list 1 2 3) '(cons integer (cons integer (cons integer)))) to test a list, but this does not mean that you will succeed with the more obvious (typep (list 1 2 3) '(list integer)). Maybe it should, though.
Erik Naggum <e...@naggum.net> writes: > For instance, given the following function definition, do you expect (foo > 0) to return nil or 0 or something else or do you expect it to signal an > error?
I expect the compiler to signal a warning and the function to signal an error. The addition can be optimized out.
> Huh? You asked it not to be initialized. Why did you expect it to be?
Because LET initializes things without being asked to, and I remembered the need to make the default NIL fit the declared type of the variable, and imagined I'd have to do something similar with the default contents of arrays too (as if there were any).
> It also seems that your confusions stem from a type theoretical > background that has failed to describe the real world and fit a > _too_ simple mathematical model of whatever they thought they saw.
I haven't studied type theory. I know C and C++ though, and there you cannot implicitly convert T** to const T**. This seems related to Common Lisp's disjoint (array X) and (array Y) types (assuming X and Y are upgraded types).
CL's OR and SATISFIES type specifiers were quite an astonishment when I first read about them, kind of like Scheme's continuations.
> cons is a special case, just like complex.
Are there any others like them?
What if I make an array with element-type (cons symbol fixnum); is the Lisp required to upgrade that to at least CONS, or can it preserve the exact type and let me store only conses pointing to symbols and fixnums? What happens if I mutate the cons after storing it in the array -- is that OK as long as I don't use that element of the array? With subtypes of COMPLEX, there are no such problems, I think.
> Because LET initializes things without being asked to, [...]
No, it does not. This is a confusion in your own mind. Only you can fix it. Please do not state your conclusions as if they were _observations_ from a specification. Binding and initialization are conceptually so far apart that I have a hard time figuring out how to respond to you, but you have gone astray somewhere, thinking they are the same. Please backtrack to that point and take the right path. I fear that several other weird conclusions come from this strange mistake. Perhaps you believe that a variable is some kind of data storage that is initialized to something in a let binding, just like a cons cell is a kind of data storage that is explicitly initialized to hold some data when you call the constructor cons. If you think at this C level, maybe it works for you to consider a binding as affecting a pointer in a variable and initialization as affecting the pointed-to object. But please, do not think at the C level -- the more you succeed in doing so, the harder it will be to get back to the truth when you realize that you are stuck. It _will_ be painful.
> I haven't studied type theory.
Good for you, but you have absorbed a great deal of trash from it, anyway. Sometimes, one has to discard what one think one knows in order to learn what is right in both the old and the new context.
> I know C and C++ though, and there you cannot implicitly convert T** to > const T**. This seems related to Common Lisp's disjoint (array X) and > (array Y) types (assuming X and Y are upgraded types).
No, not at all related. (array (signed-byte 32)) and (array single-float) are disjoint for _exactly_ the same reason that int[] and float[] are.
> CL's OR and SATISFIES type specifiers were quite an astonishment when I > first read about them, kind of like Scheme's continuations.
Types in Common Lisp are named partitions of a mathematical value space. Types in C are hardware implementations of partitions of the hardware value space, plus a little compile-time noise thrown in for good measure. The C type concept is easy to understand from a Common Lisp point of view, but coming from C, you have to realize that your "type" concept is really a very peculiar special case of a much broader, general concept. This is why C and the like are horrible languages to expose beginners to.
> Are there any others like them?
Not that I can recall, but you should not worry about these things now.
> What if I make an array with element-type (cons symbol fixnum); is the > Lisp required to upgrade that to at least CONS, or can it preserve the > exact type and let me store only conses pointing to symbols and > fixnums? What happens if I mutate the cons after storing it in the > array -- is that OK as long as I don't use that element of the array? > With subtypes of COMPLEX, there are no such problems, I think.
The specialized array is a concession to hardware. The type is upgraded to the most fitting hardware-supported type available. E.g., you could ask for an array of 32-bit integers, or floating point numbers of single or double precision (but not both). If you asked for anything that would store any type of Lisp object, as opposed to _some_ types of fast and hardware-supported objects, your type would be upgraded to type t with no questions asked.
My advice to you at this stage in our Lisp experience is to drop _all_ of your concerns about types. Do not think about it. Force yourself _not_ to think about types. Think about _values_.
In article <3204391641332...@naggum.net>, Erik Naggum wrote: >* Kalle Olavi Niemitalo <k...@iki.fi> >> Because LET initializes things without being asked to, [...]
> No, it does not. This is a confusion in your own mind. Only you can fix > it. Please do not state your conclusions as if they were _observations_ > from a specification. Binding and initialization are conceptually so far > apart that I have a hard time figuring out how to respond to you, but you > have gone astray somewhere, thinking they are the same. Please backtrack > to that point and take the right path. I fear that several other weird > conclusions come from this strange mistake. Perhaps you believe that a > variable is some kind of data storage that is initialized to something in > a let binding, just like a cons cell is a kind of data storage that is > explicitly initialized to hold some data when you call the constructor > cons. If you think at this C level, maybe it works for you to consider a
One who thinks in C should have no problem seeing the difference between the association of a name with location and the storage of an initial value in that location. Binding and initialization are also far apart in C. Fo far apart that one is often done without the other, without any diagnosis. :)
>> I know C and C++ though, and there you cannot implicitly convert T** to >> const T**. This seems related to Common Lisp's disjoint (array X) and >> (array Y) types (assuming X and Y are upgraded types).
> No, not at all related. (array (signed-byte 32)) and (array single-float) > are disjoint for _exactly_ the same reason that int[] and float[] are.
And T** and const T** are also disjoint for the same reason. T* and const T* are distinct, incompatible types. So types derived from them are also distinct, incompatible types. Think of T* as X and const T* as Y.
That you can assign T* to const T* is a special exception, which recognizes a special closeness between two incompatible types. That exception is not inherited by derived types.
A similar relationship is recognized between the floating and integral types; conversions are allowed which do not extend to derived pointer types.
In article <MM157.2316$0C.45...@news1.rdc1.bc.home.com>, Kaz Kylheku wrote: >initial value in that location. Binding and initialization are also far >apart in C. Fo far apart that one is often done without the other, >without any diagnosis. :)
Of course, I meant ``So far apart'', but I was chewing on some food.
In article <3204391641332...@naggum.net>, Erik Naggum <e...@naggum.net> wrote:
>* Kalle Olavi Niemitalo <k...@iki.fi> >> Because LET initializes things without being asked to, [...]
> No, it does not. This is a confusion in your own mind. Only you can fix > it. Please do not state your conclusions as if they were _observations_ > from a specification. Binding and initialization are conceptually so far > apart that I have a hard time figuring out how to respond to you, but you > have gone astray somewhere, thinking they are the same.
CL doesn't provide any way to bind a lexical variable without initializing it. So even though they're conceptually far apart, it's hard to think about binding without initialization also coming to mind. Perhaps instead of "without being asked to", a better phrasing would be "even if it's not desired." Leaving out the initialization form looks intuitively like a request not to initialize (if there were a way to do it, this would probably be the syntax, just as omitting :INITIAL-xxx is for arrays). The typical style of use is to leave out the initializer when you don't care (you plan on SETQing before accessing it) and explicitly initialize to NIL when this initial value is important. In this respect, letting it default is conceptually similar to "without being asked to."
This is the first time I've dared respond to a post by Erik in several months (actually, it's one of the first ones I've seen from him in a while, but I've not been reading any of the long threads like "Engineering envy"). I don't think anything in the above paragraph can be interpreted as hateful, but I'm never sure how he'll take my messages.
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <bar...@genuity.net> writes: > In article <3204391641332...@naggum.net>, Erik Naggum <e...@naggum.net> wrote: > >* Kalle Olavi Niemitalo <k...@iki.fi> > >> Because LET initializes things without being asked to, [...]
> > No, it does not. This is a confusion in your own mind. Only you can fix > > it. Please do not state your conclusions as if they were _observations_ > > from a specification. Binding and initialization are conceptually so far > > apart that I have a hard time figuring out how to respond to you, but you > > have gone astray somewhere, thinking they are the same.
> CL doesn't provide any way to bind a lexical variable without initializing > it. So even though they're conceptually far apart, it's hard to think > about binding without initialization also coming to mind. Perhaps instead > of "without being asked to", a better phrasing would be "even if it's not > desired." Leaving out the initialization form looks intuitively like a > request not to initialize (if there were a way to do it, this would > probably be the syntax, just as omitting :INITIAL-xxx is for arrays). The > typical style of use is to leave out the initializer when you don't care > (you plan on SETQing before accessing it) and explicitly initialize to NIL > when this initial value is important. In this respect, letting it default > is conceptually similar to "without being asked to."
I concur with this.
However, [not speaking to Barry now but to the original poster], it's so rare that an implementation actually specializes storage associated with a LET to make it "smaller" than is needed to represent a full pointer, that I think another way to look at it is to say that it really just doesn't, in practice, cost anything to say the variable initially holds a value of a specialized type. And you can always use either LOCALLY or THE or yet another let binding to arrange for the remaining uses of the variable to be properly type-constrained even if the point-of-binding is not type constrained. So, for example, if you want (let (x) (blah) (setq x (compute-init-array-initial-value)) ... uses of array x ...) you can do (let (x) (blah) (setq x (compute-init-array-initial-value)) (locally (declare (type array x)) ...)) etc.
> This is the first time I've dared respond to a post by Erik in several > months (actually, it's one of the first ones I've seen from him in a while, > but I've not been reading any of the long threads like "Engineering envy"). > I don't think anything in the above paragraph can be interpreted as > hateful, but I'm never sure how he'll take my messages.
> CL doesn't provide any way to bind a lexical variable without > initializing it.
Wrong. Lexical variables are bound to pre-existing objects, initialized elsewhere and usually elsewhen (that should have been a word).
> This is the first time I've dared respond to a post by Erik in several > months (actually, it's one of the first ones I've seen from him in a > while, but I've not been reading any of the long threads like > "Engineering envy"). I don't think anything in the above paragraph can > be interpreted as hateful, but I'm never sure how he'll take my messages.
Your personal need to post this crap speaks volumes about your hatred and other personal problems. Keep them both off the Net. You do not _have_ to post such filth to attempt to elevate yourself. You still reek of the place such things originate. I suggest you refrain from replying to me at all when you cannot even imagine posting anything without adding such demeaning insults to try to make yourself a better person at my expense. Anyone with half a brain can see through your pathetic attempt to shift the blame for your personal problems onto me. Just _quit_ it, idiot.
> * Barry Margolin <bar...@genuity.net> > > I don't think anything in the above paragraph can > > be interpreted as hateful, but I'm never sure how he'll take my messages.
In article <sfwzoa3qh4o....@world.std.com>, Kent M Pitman <pit...@world.std.com> wrote:
>However, [not speaking to Barry now but to the original poster], >it's so rare that an implementation actually specializes storage >associated with a LET to make it "smaller" than is needed to represent a full >pointer, that I think another way to look at it is to say that it really just >doesn't, in practice, cost anything to say the variable initially holds a >value of a specialized type.
And the reason why arrays have specialized types is because there are many common uses of arrays where it *does* pay to reduce the size of each element. When large amounts of similar data are accessed, arrays are probably the most common storage mechanism. If the compiler can optimize out the type dispatching in the inner loop that processes the array, it can have a significant impact.
There have also been some implementations where the storage space for a fixnum or single-float is half that of a pointer that's used for general references. If you have a huge array, reducing its footprint in half can improve performance quite a bit due to reduced paging. As memory has gotten cheaper this has become less significant, although not as much as you'd think because applications have also grown in size (some say "bloat") to take up the available space.
But the general point is that arrays are more often used for the types of things that can most benefit from these types of compiler optimizations. While it's also common to iterate through lists like this, I don't think they tend to grow to the enormous sizes that arrays sometimes do. The types of applications that require such huge data sets often match arrays' properties pretty well (this is why vector processors are a common feature of supercomputers).
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
In article <3204438685115...@naggum.net>, Erik Naggum <e...@naggum.net> wrote:
>* Barry Margolin <bar...@genuity.net> >> CL doesn't provide any way to bind a lexical variable without >> initializing it.
> Wrong. Lexical variables are bound to pre-existing objects, initialized > elsewhere and usually elsewhen (that should have been a word).
Are we talking about different things? I was talking about initializing the variable, not the contents of the object that it refers to.
>> This is the first time I've dared respond to a post by Erik in several >> months (actually, it's one of the first ones I've seen from him in a >> while, but I've not been reading any of the long threads like >> "Engineering envy"). I don't think anything in the above paragraph can >> be interpreted as hateful, but I'm never sure how he'll take my messages.
> Your personal need to post this crap speaks volumes about your hatred and > other personal problems.
You manage to read hatred into whatever I write. I didn't write that because I hate you, I wrote it because I was *scared* of you, since no matter what I write you always manage to turn it into a sign of hatred.
I just can't win.
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
>>>>> "BarMar" == Barry Margolin <bar...@genuity.net> writes:
BarMar> ... If you have BarMar> a huge array, reducing its footprint in half can improve BarMar> performance quite a bit due to reduced paging. As memory BarMar> has gotten cheaper this has become less significant, BarMar> although not as much as you'd think because applications BarMar> have also grown in size (some say "bloat") to take up the BarMar> available space. ...
Just an addition, (and I am sure you know this but the OP might not) storing the data itself directly in the array as opposed to pointers gets you a big win due to caching if your access pattern to the array has some locality. As you point out, paging is less of a concern now but the speed difference between main memory and fast l1 and l2 caches seem to be increasing, giving rise to a similar concern.
* Barry Margolin wrote: > There have also been some implementations where the storage space for a > fixnum or single-float is half that of a pointer that's used for general > references. If you have a huge array, reducing its footprint in half can > improve performance quite a bit due to reduced paging. As memory has > gotten cheaper this has become less significant, although not as much as > you'd think because applications have also grown in size (some say "bloat") > to take up the available space.
Even without paging it can really help, both because just walking through the array requires half the memory fetches, and because you don't have to make at least one further fetch to get at the actual object. Even without the pointer-is-two-single-floats problem you still save a fair bit of memory traffic, and the traffic you have probably has better characteristics for caches.
> Are we talking about different things? I was talking about initializing > the variable, not the contents of the object that it refers to.
Yes, that is the point of difference and the reason one is called binding and the other is called initialization. Programming languages that treat their lexical variables as data storage perpetuate the notion that they take space of the same kind as data storage in objects. There are some very important differences that make them worthy of different concepts. You always bind a variable to an object, but you may initialize an object with some other data. If you just allocate space for something in a variable, that may just not be good coding style. Several languages have made it so much easier in recent years to have lexical variables defined where they are first needed, but I think (Common) Lisp was there first, although we do have support for variables-as-temporary-data-storage, too, like many other things that _sometimes_ come in handy, despite general rules to the contrary.
> You manage to read hatred into whatever I write.
I read you to want the general public to applaud you moral superiority over me, because you could behave like a normal human being and actually manage to be to the point and _not_ attack me out of the blue, as opposed to me, whom you expect to slaughter you in response, but what did you do in that last paragraph? You went out of your wray to depict me as someone who _will_ respond hostilely to absolutely _anything_, while wearing a halo and a smirk as _you_ say it. Hatred takes many forms. The kind of holier-than-thou disrespect you simply cannot help yourself from spewing is one form that several other (groups of) people who have experienced systematic hatred know all too well, and not surprisingly, those who have built their hatred into their personality, do not even recognize it when they show it to people.
It is blindingly obvious that you hate _me_, but I only hate what you keep _doing_ to me. If you simply _stopped_ your insane need to paint me as the devil himself, maybe you would be treated as something other than the insanely hateful person you continue to look like. It does not take much: Simply _refrain_ from accusing people, directly or indirectly, of things they have not even done, and especially not _yet_.
> I didn't write that because I hate you, I wrote it because I was *scared* > of you, since no matter what I write you always manage to turn it into a > sign of hatred.
Just behave. You do not have to point out that you have behaved and imply that others have not before they had a chance to do anything. If you poke people in the eye and say "look, I did not kill you, but God knows what someone like _you_ will do next", what do you _expect_?
Well, one way is to show you the same kind of _disrespect_ you show others and exclaim extactically that "look, everybody, Barry Margolin is so happy he can actually behave like a normal human being that he must tell us and virtually asks us all to applaud him! HOORAY for Barry!", but I somehow maintain that respectful behavior towards others is the baseline. That is why I keep getting angry at people like you who seem unable to deal with others respectfully no matter _what_ they do to you.
> I just can't win.
Yes, you can. That you have failed to figure it out, frankly amazes me. Just make an effort to treat people _fairly_ and _respectfully_ when they have, in fact, not attacked you. As long as you keep doing your moral superiority stunt, expect hostile response. Try it with other people and see if _maybe_ it is how you behave that is the cause. How would _you_ react if someone took every opportunity to imply that you were insane or at the very least a very, very bad person, no matter what they did? If you feel like you "just can't win", just _try_ to imagine how you have _purposefully_ made me feel for the longest time! If you do not like it happening to yourself, consider the fact that you have other options than constantly doing it to somebody else.
Just behave, Barry Margolin. You do not need to tell anyone and you most certainly do not need to be applauded for it when you accomplish it. I assume that you are sufficiently smart to figure out that if you insult people, you will not be treated nicely in return. I assume, however, that you are not _willing_ to consider the fact that you insult people with your moral superiority stunts and your disrespectfulness because something (probably a bad religion) tells you that you have the _right_ to do that to other people. I know from the past that you have a very hard time actually dealing with people based on what they do -- you have been guilty several times in the past of not even being able to _see_ what people are doing, but have imputed evil to their intentions no matter what you actually see. You should have recognized it, since you have done it to me for years, much like some of the other kooks here who have a hard time dealing with reality, but somehow that moral superority of yours have kept you from realizing it. Look at your own behavior and see if you would let _me_ "win". You _know_ that I let people off the hook if they stop doing the _specific_ things I criticize them for, but you keep being _unspecific_ and _not_ letting me off the hook. Do you need to be treated the same before you realize what you are doing, or are you smart enough to figure it out on your own? It is your choice.
You are among the most _unfair_ people I have had the displeasure of dealing with, Barry Margolin, and it will take me some time to recover from the hostility I feel towards you and expect from you, which you have managed to inflame _again_, out of nowhere. I _never_ know when you will come out of nowhere and attack me brutally for things I have not even _done_. You could at least have confined yourself to stuff I _have_ done -- any sane person can always find something _real_ to attack in another person if he wants to, but the insane need to invent evil that is not there. Since you have done the latter towards me for a _very_ long time, I assume it will require massive effort on your part to disestablish this vile habit of yours. I wish you the best of look, though. It sure will be eaiser to deal with you if you can deal with me as a _person_, and not the scary monster you appear to see when you just see my name.
#:Erik -- There is nothing in this message that under normal circumstances should cause Barry Margolin to announce his moral superiority over others, but one never knows how he needs to behave to maintain his belief in it.
In article <87r8veaxo8....@nkapi.internal>, Bulent Murtezaoglu <b...@acm.org> wrote:
>Just an addition, (and I am sure you know this but the OP might not) >storing the data itself directly in the array as opposed to pointers >gets you a big win due to caching if your access pattern to the >array has some locality. As you point out, paging is less of a >concern now but the speed difference between main memory and fast l1 >and l2 caches seem to be increasing, giving rise to a similar concern.
I didn't mention it because most Lisp implementations use an immediate representation for fixnums. So even if you don't declare the type, you get this benefit.
However, if the array type is short-float, most implementations would box them unless you specialize the array. You get a big win by avoiding boxing and unboxing, as well as better cache utilization.
-- Barry Margolin, bar...@genuity.net Genuity, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups. Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.