From ... Path: archiver1.google.com!newsfeed.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!npeer.kpnqwest.net!nreader1.kpnqwest.net.POSTED!not-for-mail Newsgroups: comp.lang.lisp Subject: Re: array types (Re: Stupid question) References: Mail-Copies-To: never From: Erik Naggum Message-ID: <3204375347190450@naggum.net> Organization: Naggum Software, Oslo, Norway Lines: 99 User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Tue, 17 Jul 2001 16:15:51 GMT X-Complaints-To: newsmaster@Norway.EU.net X-Trace: nreader1.kpnqwest.net 995386551 193.71.66.1 (Tue, 17 Jul 2001 18:15:51 MET DST) NNTP-Posting-Date: Tue, 17 Jul 2001 18:15:51 MET DST Xref: archiver1.google.com comp.lang.lisp:13257 * Kalle Olavi Niemitalo > 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? (defun foo (bar &aux zot) (declare (optimize (speed 3) (safety 0) (debug 0) (space 3)) (type fixnum bar zot)) (+ bar zot)) 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 ), 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 )? 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 '(vector ))? 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 -- Travel is a meat thing.