From: Karol Skocik
Subject: defclass types confusion
Date: 
Message-ID: <1139520110.551192.190780@f14g2000cwb.googlegroups.com>
Hi,
  I hope that some experienced lisper can help me. In SBCL 0.98 on
Linux, I want to make a class arena :

(defclass entity ()
  ())

(defclass cell ()
  ((entity :type entity :accessor entity)
   (pseudo-z :type fixed :accessor pseudo-z)))

(defclass arena ()
  ((grid :type (simple-array cell (* *)) :initarg :grid :accessor
grid)))

(defun make-arena (&key (x-dim 40) (y-dim 30))
  (make-instance 'arena :grid (make-array (list x-dim y-dim)
:element-type 'cell)))

so the arena shoud be 2d array of cells. Now, this :

TACTIX> (setf *arena* (make-arena))
#<ARENA {AB7B761}>
TACTIX> (type-of (slot-value *arena* 'grid))
(SIMPLE-ARRAY T (40 30))
TACTIX> (type-of (aref (slot-value *arena* 'grid) 0 0))
BIT

So, I declare in defclass the grid to be a 2d array of cells.
When I ask for the type of grid - I get a 2d array of T.
And when I ask for element of grid - I get BIT.

Why is this so, and how can I have a 2d array of cells using the
defclass's type declarations?

Thanks, 
  Karol

From: Karol Skocik
Subject: Re: defclass types confusion
Date: 
Message-ID: <1139524147.106416.110490@g43g2000cwa.googlegroups.com>
Thanks guys. Works ok now. 

Good night,
  Karol
From: Pascal Bourguignon
Subject: Re: defclass types confusion
Date: 
Message-ID: <87ek2ci5dy.fsf@thalassa.informatimago.com>
"Karol Skocik" <············@gmail.com> writes:

> Hi,
>   I hope that some experienced lisper can help me. In SBCL 0.98 on
> Linux, I want to make a class arena :
>
> (defclass entity ()
>   ())
>
> (defclass cell ()
>   ((entity :type entity :accessor entity)
>    (pseudo-z :type fixed :accessor pseudo-z)))
>
> (defclass arena ()
>   ((grid :type (simple-array cell (* *)) :initarg :grid :accessor
> grid)))
>
> (defun make-arena (&key (x-dim 40) (y-dim 30))
>   (make-instance 'arena :grid (make-array (list x-dim y-dim)
> :element-type 'cell)))
>
> so the arena shoud be 2d array of cells. Now, this :
>
> TACTIX> (setf *arena* (make-arena))
> #<ARENA {AB7B761}>
> TACTIX> (type-of (slot-value *arena* 'grid))
> (SIMPLE-ARRAY T (40 30))
> TACTIX> (type-of (aref (slot-value *arena* 'grid) 0 0))
> BIT
>
> So, I declare in defclass the grid to be a 2d array of cells.
> When I ask for the type of grid - I get a 2d array of T.
> And when I ask for element of grid - I get BIT.

You didn't provide a conforming program, so you get whatever.

When you specify the :element-type to make-array, you must also
provide a compatible :initial-element.

Your implementation seems to like using 0 as default initial element.
It then allocates an array with element-type (or cell bit) [0 is of
type bit, subtype of fixnum, subtype of integer, ... subtype of
number], and the only type known to your implementation that contains
(or cell bit)  is T.


> Why is this so, and how can I have a 2d array of cells using the
> defclass's type declarations?


(defclass empty-cell (cell) ())
(defmethod entity   ((self empty-cell)) (error "This is an empty cell"))
(defmethod pseudo-z ((self empty-cell)) (error "This is an empty cell"))

Then use:

(make-array (list x-dim y-dim) :element-type 'cell
                               :initial-element (make-instance 'empty-cell))


It shouldn't matter much: an array that can contain CLOS objects such
as instances of CELL, can contain any kind of object, so you could use
as well:

  (make-array (list x-dim y-dim) :initial-element nil)

allowing any type of elements, including instances of cell and nil,
which gives you less work in declaring an empty-cell class.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Christophe Rhodes
Subject: Re: defclass types confusion
Date: 
Message-ID: <sqbqxg5h6t.fsf@cam.ac.uk>
Pascal Bourguignon <······@informatimago.com> writes:

> "Karol Skocik" <············@gmail.com> writes:
>
>> Hi,
>>   I hope that some experienced lisper can help me. In SBCL 0.98 on
>> Linux, I want to make a class arena :
>>
>> (defclass entity ()
>>   ())
>>
>> (defclass cell ()
>>   ((entity :type entity :accessor entity)
>>    (pseudo-z :type fixed :accessor pseudo-z)))
>>
>> (defclass arena ()
>>   ((grid :type (simple-array cell (* *)) :initarg :grid :accessor
>> grid)))
>>
>> (defun make-arena (&key (x-dim 40) (y-dim 30))
>>   (make-instance 'arena :grid (make-array (list x-dim y-dim)
>> :element-type 'cell)))
>>
>> so the arena shoud be 2d array of cells. Now, this :
>>
>> TACTIX> (setf *arena* (make-arena))
>> #<ARENA {AB7B761}>
>> TACTIX> (type-of (slot-value *arena* 'grid))
>> (SIMPLE-ARRAY T (40 30))
>> TACTIX> (type-of (aref (slot-value *arena* 'grid) 0 0))
>> BIT
>>
>> So, I declare in defclass the grid to be a 2d array of cells.
>> When I ask for the type of grid - I get a 2d array of T.
>> And when I ask for element of grid - I get BIT.
>
> You didn't provide a conforming program, so you get whatever.

This isn't completely true, but ok.

> When you specify the :element-type to make-array, you must also
> provide a compatible :initial-element.

This is not true at all.

> Your implementation seems to like using 0 as default initial element.
> It then allocates an array with element-type (or cell bit) [0 is of
> type bit, subtype of fixnum, subtype of integer, ... subtype of
> number], and the only type known to your implementation that contains
> (or cell bit)  is T.

This is just complete rubbish.

What actually happens is the following.  In the call
  (make-array (list x-dim y-dim) :element-type 'cell)
the first question the implementation asks is "what is the
upgraded-array-element-type of the type CELL".  Nothing to do with any
such type as (OR CELL BIT).  (The question of
upgraded-array-element-type is "what is the most specialised kind of
array can I construct which can contain all objects of type CELL".)
In this implementation, as in all CL implementations that I know of,
this answer is T.

This means that the type (ARRAY CELL (* *)) is, except for declaration
purposes, the same as (ARRAY T (* *)), in this implementation as in
all implementations that I know of; and additionally the type
declaration for (ARRAY CELL (* *)) does not mean what you think it
means: specifically, it does not mean that the object is an array that
contains only CELLs; it means that accesses to the object within the
scope of the declaration involve reading and writing only CELLs.

There is then no need to provide a compatible :initial-element,
because you never need to.  (It /is/, however true that then reading
an element is undefined, but this implementation has zeroed the array
so nothing terrifying happens.)  The reason that the TYPE-OF returns
BIT is because TYPE-OF does not care about any declarations, but acts
on the object it's given directly, which is indeed 0 (so BIT, rather
than FIXNUM or something mildly useful, is returned for complicated
unrelated reasons).

The remedies that Pascal suggests, despite the confusion that I've
tried to address here, are on the right track: initialize your array
with some valid data first.  (I'd be wary of doing something like
  :initial-element (make-instance 'empty-cell)
because this fills the array with n copies of the same object rather
than n different empty-cell objects.)

Christophe