Subject: Re: array types (Re: Stupid question)
From: Erik Naggum <erik@naggum.net>
Date: Tue, 17 Jul 2001 16:15:51 GMT
Newsgroups: comp.lang.lisp
Message-ID: <3204375347190450@naggum.net>

* Kalle Olavi Niemitalo <kon@iki.fi>
> 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 <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
-- 
  Travel is a meat thing.