* (array-element-type (MAKE-ARRAY '(2)
:ELEMENT-TYPE 'INTEGER
:INITIAL-CONTENTS '(1 2)))
=> T
Why does this function exist? It doesn't seem to do much.
--Dan
------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
cl-match: expressive pattern matching in Lisp
http://common-lisp.net/project/cl-match/
danb <·········@gmail.com> writes:
> * (array-element-type (MAKE-ARRAY '(2)
> :ELEMENT-TYPE 'INTEGER
> :INITIAL-CONTENTS '(1 2)))
> => T
>
> Why does this function exist? It doesn't seem to do much.
See also the result of:
(upgraded-array-element-type 'integer)
vs.
(upgraded-array-element-type '(unsigned-byte 8))
(UNSIGNED-BYTE 8) could be any type for which your Lisp has a
specialized array representation.
Zach
danb <·········@gmail.com> writes:
> * (array-element-type (MAKE-ARRAY '(2)
> :ELEMENT-TYPE 'INTEGER
> :INITIAL-CONTENTS '(1 2)))
> => T
>
> Why does this function exist? It doesn't seem to do much.
Well, it reveals what the implementation does in the way of element
type optimization. If it returns T a lot, I suppose you're really
complaining that the implementation doesn't do certain optimizations
you might wish for. Although in this case, I think that's not really
so.
In this case, at least, remember that INTEGER is all integers, not
just fixnums. It includes bignums, in other words. So that means the
array must be capable of storing a full pointer, just in case there is
a bignum in there. At that point, why _wouldn't_ the implementation
want to just upgrade the array element type to T? There's no
advantage of a specialized type. The case where you're likely to get
specialized types is where the nature of the data admits the
possibility of compact storage.
Note, too, that an implementation will dynamically check the specific
data that you have stored in the array to figure out what array
element type to allocate, since you might change those values later
and it doesn't want to choose another representation upon your doing
that. If you really want to promise not to make such a change, you
want to try a :ELEMENT-TYPE '(INTEGER 1 2), or maybe '(UNSIGNED-BYTE 2)
or '(MEMBER 1 2) or some such thing. (I wouldn't count on
implementations to do well with the MEMBER type specifier here, but
some might.) Absent such a "promise" in play, there's no way for a
compiler to help you. But either way, the initial contents is a red
herring here; don't let yourself believe you've asked for a compact
representation of that particular array just because you used certain
initial data. Such values are mere coincidence/accident as far as the
allocation of an appropriate storage area goes.
From: Jeronimo Pellegrini
Subject: Re: Function ARRAY-ELEMENT-TYPE
Date:
Message-ID: <fvnlu1$5lq$1@aioe.org>
On 2008-05-05, danb <·········@gmail.com> wrote:
> * (array-element-type (MAKE-ARRAY '(2)
> :ELEMENT-TYPE 'INTEGER
> :INITIAL-CONTENTS '(1 2)))
>=> T
>
> Why does this function exist? It doesn't seem to do much.
Try this:
* (array-element-type (MAKE-ARRAY 2 :ELEMENT-TYPE 'double-float
:INITIAL-CONTENTS '(1d0 2d0)))
==> DOUBLE-FLOAT
This is with SBCL.
Clisp returns T; ECL returns double-float...
Someone please correct me if I'm wrong: that is because the standard
allows Lisp implementations to upgrade the element type: Clisp then
can upgrade "double-float" to "T"; that is also why I can do this:
[1]> (setq a (MAKE-ARRAY 2 :ELEMENT-TYPE 'double-float :INITIAL-CONTENTS
'(1d0 2d0)))
#(1.0d0 2.0d0)
[2]> a
#(1.0d0 2.0d0)
[3]> (array-element-type a)
T
[4]> (setf (aref a 0) 'x)
X
[5]>
[5]> a
#(X 2.0d0)
I suppose this is because it all depends on how the Lisp implementation
will represent the array internally: since SBCL will actually implement
the array of double-floats in a similar way as a C array of doubles,
then the element-type is not upgraded to T. Since (again, I'm guessing)
Clisp stores pointers to actual elements, then the element-type is T
(because, well, pointers can point to anything, not just double-floats).
Am I wrong?
J.
In article
<····································@p25g2000hsf.googlegroups.com>,
danb <·········@gmail.com> wrote:
> * (array-element-type (MAKE-ARRAY '(2)
> :ELEMENT-TYPE 'INTEGER
> :INITIAL-CONTENTS '(1 2)))
> => T
>
> Why does this function exist? It doesn't seem to do much.
Which function? array-element-type ?
It returns the type T in your example. That's fine.
Your Lisp has decided that the element type of
the above array is of type T. Means it
does not have a special array type for
arrays with element type INTEGER.
Read about Array Upgrading:
http://www.lisp.org/HyperSpec/Body/sec_15-1-2-1.html
Here is an example where a Lisp does not upgrade an
element type:
? (array-element-type (MAKE-ARRAY '(2)
:ELEMENT-TYPE 'fixnum
:INITIAL-CONTENTS '(1 2)))
FIXNUM
See also these examples:
? (array-element-type (MAKE-ARRAY '(2)
:ELEMENT-TYPE '(unsigned-byte 4)
:INITIAL-CONTENTS '(1 2)))
(UNSIGNED-BYTE 8)
? (array-element-type (MAKE-ARRAY '(2)
:ELEMENT-TYPE '(unsigned-byte 9)
:INITIAL-CONTENTS '(1 2)))
(UNSIGNED-BYTE 16)
>
> --Dan
>
> ------------------------------------------------
> Dan Bensen
> http://www.prairienet.org/~dsb/
>
> cl-match: expressive pattern matching in Lisp
> http://common-lisp.net/project/cl-match/
--
http://lispm.dyndns.org/
On May 5, 2:11 pm, Rainer Joswig <······@lisp.de> wrote:
> Your Lisp has decided that the element type of
> the above array is of type T. Means it
> does not have a special array type for
> arrays with element type INTEGER.
You mean it's used to choose between different
array implementations?
> Read about Array Upgrading:
> http://www.lisp.org/HyperSpec/Body/sec_15-1-2-1.html
There's nothing there about why upgrading occurs.
So there's no way to automatically create type
declarations for all the elements of an array?
That's what I thought :element-type would do.
--Dan
------------------------------------------------
Dan Bensen http://www.prairienet.org/~dsb/
cl-match: expressive pattern matching in Lisp
ttp://common-lisp.net/project/cl-match/
In article
<····································@s50g2000hsb.googlegroups.com>,
danb <·········@gmail.com> wrote:
> On May 5, 2:11 pm, Rainer Joswig <······@lisp.de> wrote:
> > Your Lisp has decided that the element type of
> > the above array is of type T. Means it
> > does not have a special array type for
> > arrays with element type INTEGER.
>
> You mean it's used to choose between different
> array implementations?
>
> > Read about Array Upgrading:
> > http://www.lisp.org/HyperSpec/Body/sec_15-1-2-1.html
>
> There's nothing there about why upgrading occurs.
>
> So there's no way to automatically create type
> declarations for all the elements of an array?
> That's what I thought :element-type would do.
With :element-type you say which element type you want.
After upgrading you get either the same element type
or a supertype. The Lisp system determines which element types
it supports and which element type you get. After upgrading,
the actual array can hold elements of the the upgraded
element type (not the one you may have initially wished).
This means in your case, when you request INTEGER and you
get T, the array actually supports all elements of type
T (in this case all types, since T is the supertype of
all types). So you request an ARRAY of INTEGERs,
but you really get a an ARRAY of T.
>
> --Dan
>
> ------------------------------------------------
> Dan Bensen http://www.prairienet.org/~dsb/
>
> cl-match: expressive pattern matching in Lisp
> ttp://common-lisp.net/project/cl-match/
--
http://lispm.dyndns.org/
danb <·········@gmail.com> writes:
> On May 5, 2:11 pm, Rainer Joswig <······@lisp.de> wrote:
>> Your Lisp has decided that the element type of
>> the above array is of type T. Means it
>> does not have a special array type for
>> arrays with element type INTEGER.
>
> You mean it's used to choose between different
> array implementations?
No, it's an implementation introspection API. There are a lot of
features of Common Lisp that are there only to let applications to
behave conformantly on very diverse conformant implementations.
The Common Lisp standard doesn't prescribe how arrays shall be laid
out in memory. It's up to the implementation to decide. But it will
let your application know what the implementation does, so you can
write more portable code. That is, if you need to know it at all.
>> Read about Array Upgrading:
>> http://www.lisp.org/HyperSpec/Body/sec_15-1-2-1.html
>
> There's nothing there about why upgrading occurs.
>
> So there's no way to automatically create type
> declarations for all the elements of an array?
> That's what I thought :element-type would do.
Yes, that's what :element-type does. If you want to remember the
exact type you specified to make-array, then you have to do that
bookkeeping yourself.
Note moreover that in general, when you give a type expression to
lisp, it can return it to you quite massaged, even for an equal type.
(let* ((my-type '(integer 0 1))
(normalized-type (array-element-type (make-array 0 :element-type my-type))))
(assert (and (subtypep my-type normalized-type)
(subtypep normalized-type my-type)))
(values my-type normalized-type))
#+sbcl
--> (INTEGER 0 1) ;
BIT
So you cannot rely on your implementation to return you the same type
expression as you wrote, you have to do that kind of bookkeeing
yourself.
--
__Pascal Bourguignon__
> > On May 5, 2:11 pm, Rainer Joswig <······@lisp.de> wrote:
> >> Your Lisp has decided that the element type of
> >> the above array is of type T. Means it
> >> does not have a special array type for
> >> arrays with element type INTEGER.
> danb <·········@gmail.com> writes:
> > You mean it's used to choose between different
> > array implementations?
On May 6, 2:27 am, Pascal J. Bourguignon wrote:
> No, it's an implementation introspection API.
Right, my mistake. What I meant to suggest was that
:element-type helps the system choose an implementation
for the array, and #'array-element-type reports what
the system chose.
> > So there's no way to automatically create type
> > declarations for all the elements of an array?
> > That's what I thought :element-type would do.
> Yes, that's what :element-type does.
Not quite. I thought it would do the equivalent of
(declaim (desired-type (aref my-array <indices>)))
for each element in the array, but apparently that
wouldn't be allowed anyway. The only type error
I've seen sbcl generate from :element-type is in
the array's *initial* contents, not when I change
the contents later.
> (let ((a (make-array '(1)
:element-type 'string
:initial-contents '("FOO"))))
(setf (aref a 0) :foo)
a)
#(:FOO)
This even works inside a compiled function.
I thought it would generate an error.
Thanks Pascal, I appreciate the help.
------------------------------------------------
Dan Bensen http://www.prairienet.org/~dsb/
cl-match: expressive pattern matching in Lisp
http://common-lisp.net/project/cl-match/
danb <·········@gmail.com> writes:
>> > So there's no way to automatically create type
>> > declarations for all the elements of an array?
>> > That's what I thought :element-type would do.
>
>> Yes, that's what :element-type does.
>
> Not quite. I thought it would do the equivalent of
> (declaim (desired-type (aref my-array <indices>)))
>
> for each element in the array, but apparently that
> wouldn't be allowed anyway. The only type error
> I've seen sbcl generate from :element-type is in
> the array's *initial* contents, not when I change
> the contents later.
>
>> (let ((a (make-array '(1)
> :element-type 'string
> :initial-contents '("FOO"))))
> (setf (aref a 0) :foo)
> a)
> #(:FOO)
>
> This even works inside a compiled function.
> I thought it would generate an error.
Indeed, I would have expected too an error at leat with (safety 3)...
telnet://prompt.franz.com too has the same behavior.
--
__Pascal Bourguignon__
···@informatimago.com (Pascal J. Bourguignon) writes:
> danb <·········@gmail.com> writes:
>>> > So there's no way to automatically create type
>>> > declarations for all the elements of an array?
>>> > That's what I thought :element-type would do.
>>
>>> Yes, that's what :element-type does.
>>
>> Not quite. I thought it would do the equivalent of
>> (declaim (desired-type (aref my-array <indices>)))
>>
>> for each element in the array, but apparently that
>> wouldn't be allowed anyway. The only type error
>> I've seen sbcl generate from :element-type is in
>> the array's *initial* contents, not when I change
>> the contents later.
>>
>>> (let ((a (make-array '(1)
>> :element-type 'string
>> :initial-contents '("FOO"))))
>> (setf (aref a 0) :foo)
>> a)
>> #(:FOO)
>>
>> This even works inside a compiled function.
>> I thought it would generate an error.
>
> Indeed, I would have expected too an error at leat with (safety 3)...
>
> telnet://prompt.franz.com too has the same behavior.
Note that the descrtiption of array-element-type:
http://www.franz.com/support/documentation/current/ansicl/dictentr/array-el.htm
says "Returns a type specifier which represents the actual array
element type of the array, which is the set of objects that such an
array can hold. (Because of array upgrading, this type specifier can
in some cases denote a supertype of the expressed array element type
of the array.)"
So the example above represents the expectation that the compiler would
use the "expressed element type" as the declaration, rather than the
"actual element type". This might be a reasonable request, except
that it places a larger burden on type checking when setfs are done on
the array, especially for interpreted code. When you ask for an array
a of (unsigned-byte 7) and get one back which is (unsigned-byte 8),
should (setf (aref a 0) 255) result in an error? It would defeat one
of the purposes of having specialized arrays, which is the quick
testing of values to set. So the answer is no: (setf aref) uses the
actual element type to determine limits.
--
Duane Rettig ·····@franz.com Franz Inc. http://www.franz.com/
555 12th St., Suite 1450 http://www.555citycenter.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182
P� Tue, 06 May 2008 19:01:59 +0200, skrev Pascal J. Bourguignon
<···@informatimago.com>:
> danb <·········@gmail.com> writes:
>>> > So there's no way to automatically create type
>>> > declarations for all the elements of an array?
>>> > That's what I thought :element-type would do.
>>
>>> Yes, that's what :element-type does.
>>
>> Not quite. I thought it would do the equivalent of
>> (declaim (desired-type (aref my-array <indices>)))
>>
>> for each element in the array, but apparently that
>> wouldn't be allowed anyway. The only type error
>> I've seen sbcl generate from :element-type is in
>> the array's *initial* contents, not when I change
>> the contents later.
>>
>>> (let ((a (make-array '(1)
>> :element-type 'string
>> :initial-contents '("FOO"))))
>> (setf (aref a 0) :foo)
>> a)
>> #(:FOO)
>>
>> This even works inside a compiled function.
>> I thought it would generate an error.
>
> Indeed, I would have expected too an error at leat with (safety 3)...
>
> telnet://prompt.franz.com too has the same behavior.
>
As long as upgraded-array-element-type is t anything goes.
The problem is that the array 'forgets' the original declaration and
substitutes the upgraded one.
For 'fixnum or something of the like which isn't upgraded to 't you would
get a error for the case above.
Must admit this was a real awakener for me.
--------------
John Thingstad