From: Christian Hofer
Subject: simple vector versus simple array
Date: 
Message-ID: <ca9epp$bbs$1@online.de>
Hi,

how do you create a vector of fixnums? The most natural solution seems 
to be using a simple vector. But a simple vector - as opposed to a 
simple array - cannot be restricted to a type. So maybe, w.r.t. future 
optimization options, is it better to use a simple one-dimensional array 
from the start?  Is there a general answer to this?

Thanks,
Chris

From: Lars Brinkhoff
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <85k6yfllhf.fsf@junk.nocrew.org>
Christian Hofer <·······@gmx.de> writes:
> how do you create a vector of fixnums? The most natural solution seems
> to be using a simple vector.

        (let ((v (vector 1 2 3)))

#|
> But a simple vector - as opposed to a simple array - cannot be
> restricted to a type. So maybe, w.r.t. future optimization options,
> is it better to use a simple one-dimensional array from the start?
|#

          (make-array 3 :element-type 'fixnum :initial-contents v))

-- 
Lars Brinkhoff,         Services for Unix, Linux, GCC, HTTP
Brinkhoff Consulting    http://www.brinkhoff.se/
From: Joe Marshall
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <hdtjtnxj.fsf@ccs.neu.edu>
> Christian Hofer <·······@gmx.de> writes:
>> how do you create a vector of fixnums? 

> Lars Brinkhoff <·········@nocrew.org> writes:
>
>           (make-array 3 :element-type 'fixnum :initial-contents v))
>

Note that this might be *less* efficient than an unspecialized
vector.  Since a fixnum is usually something like (signed-byte 30),
the array may be upgraded to (signed-byte 32).  But then aref and
(setf aref) will have to box and unbox the fixnum!  If you use a
vector, the fixnum can be placed in the vector without removing the
tag. 
From: Duane Rettig
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <4smd3ayig.fsf@franz.com>
Joe Marshall <···@ccs.neu.edu> writes:

> > Christian Hofer <·······@gmx.de> writes:
> >> how do you create a vector of fixnums? 
> 
> > Lars Brinkhoff <·········@nocrew.org> writes:
> >
> >           (make-array 3 :element-type 'fixnum :initial-contents v))
> >
> 
> Note that this might be *less* efficient than an unspecialized
> vector.  Since a fixnum is usually something like (signed-byte 30),
> the array may be upgraded to (signed-byte 32).  But then aref and
> (setf aref) will have to box and unbox the fixnum!  If you use a
> vector, the fixnum can be placed in the vector without removing the
> tag. 

Correct.  Allegro CL originally had specialized vectors of type
fixnum, but the bit patterns were such that they required a shift
after an aref and before the setf.  I removed these (in favor of
arrays of type nybble (i.e. (unsigned-byte 4)) because we use those
in bit maps often, and because the utlity of the old fixnum vectors
was suspect - better optimizations were available by using arrays of
type T and declaring each access as restricted to fixnum.

But the automatic declarations that come for free with a vector of
type fixnum are such that we lose performance battles with other
CLs.  So in 7.0, where we've also increased the array-total-size-limit
to be that of most-positive-fixnum, I rearranged the array type
structure and added back the fixnum array type, but this time with
the bits in an unshifted position (so that they can be stored and
lifted without shifts).  But also, now, such arrays come with
automatic declarations on arefs built-in.

-- 
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   
From: Joe Marshall
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <wu2ei556.fsf@ccs.neu.edu>
Duane Rettig <·····@franz.com> writes:

> So in 7.0, where we've also increased the array-total-size-limit
> to be that of most-positive-fixnum, I rearranged the array type
> structure and added back the fixnum array type, but this time with
> the bits in an unshifted position (so that they can be stored and
> lifted without shifts).  But also, now, such arrays come with
> automatic declarations on arefs built-in.

Cool.
From: André Thieme
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <caqt4q$1aq$2@ulric.tng.de>
Joe Marshall schrieb:

>>Christian Hofer <·······@gmx.de> writes:
>>
>>>how do you create a vector of fixnums? 
> 
> 
>>Lars Brinkhoff <·········@nocrew.org> writes:
>>
>>          (make-array 3 :element-type 'fixnum :initial-contents v))
>>
> 
> 
> Note that this might be *less* efficient than an unspecialized
> vector.  Since a fixnum is usually something like (signed-byte 30),
> the array may be upgraded to (signed-byte 32).  But then aref and
> (setf aref) will have to box and unbox the fixnum!  If you use a
> vector, the fixnum can be placed in the vector without removing the
> tag. 

Could you please explain what "to box" and "to unbox" means?


Andr�
--
From: Joe Marshall
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <8yeml8n6.fsf@comcast.net>
Andr� Thieme <······························@justmail.de> writes:

> Joe Marshall schrieb:
>
>>>Christian Hofer <·······@gmx.de> writes:
>>>
>>>> how do you create a vector of fixnums?
>>
>>>Lars Brinkhoff <·········@nocrew.org> writes:
>>>
>>>          (make-array 3 :element-type 'fixnum :initial-contents v))
>>>
>> Note that this might be *less* efficient than an unspecialized
>> vector.  Since a fixnum is usually something like (signed-byte 30),
>> the array may be upgraded to (signed-byte 32).  But then aref and
>> (setf aref) will have to box and unbox the fixnum!  If you use a
>> vector, the fixnum can be placed in the vector without removing the
>> tag.
>
> Could you please explain what "to box" and "to unbox" means?

In most Lisp implementations, every object has a tag that indicates
what it is.  The most popular tagging scheme these days seems to be a
`lowtag' one.  If the system arranges for all object to be allocated
on 8-byte boundaries, then the bottom 3 bits of an address will always
be zero.  This is where Lisp stores the `primary' tag of the object
(the tag is stripped off before fetching the object).

In a specialized array of signed or unsigned bytes, there is no need
for a tag (and no room, either), so the numbers are stored without the
tag.  Objects without a tag are called `unboxed'.  When you fetch from
a specialized array, you convert the raw number into a tagged object.
This is called `boxing' the object.  When you store into the array,
you strip the tag off.  This is `unboxing'.

-- 
~jrm
From: Peter Seibel
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <m3n03bsb2h.fsf@javamonkey.com>
Lars Brinkhoff <·········@nocrew.org> writes:

> Christian Hofer <·······@gmx.de> writes:
>> how do you create a vector of fixnums? The most natural solution seems
>> to be using a simple vector.
>
>         (let ((v (vector 1 2 3)))
>
> #|
>> But a simple vector - as opposed to a simple array - cannot be
>> restricted to a type. So maybe, w.r.t. future optimization options,
>> is it better to use a simple one-dimensional array from the start?
> |#
>
>           (make-array 3 :element-type 'fixnum :initial-contents v))

Or slightly robust in the face of changes to v:

  (make-array (length v) :element-type 'fixnum :initial-contents v)

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Christian Hofer
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <cac2n6$9kb$1@online.de>
Lars Brinkhoff wrote:
> Christian Hofer <·······@gmx.de> writes:
> 
>>how do you create a vector of fixnums? The most natural solution seems
>>to be using a simple vector.
> 
> 
>         (let ((v (vector 1 2 3)))
> 
[snip]
Sorry for my bad English. My problem was not so much, how I can do it, 
but how it is normally done. I see in Graham's ACL, that he uses simple 
vectors and references them with svref. But for me, it looked strange to 
use svref, when I might at a later stage in programming want to optimize 
it as an array of fixnums: I would have to replace all the svref by aref 
then... But maybe (when I interpret Joe Marshall's answer correctly) 
this is not the case after all?

Chris
From: Joe Marshall
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <smd2i4vs.fsf@ccs.neu.edu>
Christian Hofer <·······@gmx.de> writes:

> Lars Brinkhoff wrote:
>> Christian Hofer <·······@gmx.de> writes:
>>
>>>how do you create a vector of fixnums? The most natural solution seems
>>>to be using a simple vector.
>>         (let ((v (vector 1 2 3)))
>>
> [snip]
> Sorry for my bad English. 

Don't worry about that, we focus on bad Lisp. 

> My problem was not so much, how I can do it, but how it is normally
> done. I see in Graham's ACL, that he uses simple vectors and
> references them with svref. But for me, it looked strange to use
> svref, when I might at a later stage in programming want to optimize
> it as an array of fixnums: I would have to replace all the svref by
> aref then... But maybe (when I interpret Joe Marshall's answer
> correctly) this is not the case after all?

The most flexible way to deal with this is via a macro.

(defmacro fixnum-vector-allocate (size)
  `(make-array ,size))

(defmacro fixnum-svref (fixnum-vector index)
  `(aref ,fixnum-vector ,index))

Now later on when you want to optimize, just change the macros:

(defmacro fixnum-vector-allocate (size)
  `(make-array ,size :element-type 'fixnum))

(defmacro fixnum-svref (fixnum-vector index)
  `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
From: Björn Lindberg
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <hcsk6yeupd6.fsf@knatte.nada.kth.se>
Joe Marshall <···@ccs.neu.edu> writes:

> Christian Hofer <·······@gmx.de> writes:
> 
> > Lars Brinkhoff wrote:
> >> Christian Hofer <·······@gmx.de> writes:
> >>
> >>>how do you create a vector of fixnums? The most natural solution seems
> >>>to be using a simple vector.
> >>         (let ((v (vector 1 2 3)))
> >>
> > [snip]
> > Sorry for my bad English. 
> 
> Don't worry about that, we focus on bad Lisp. 
> 
> > My problem was not so much, how I can do it, but how it is normally
> > done. I see in Graham's ACL, that he uses simple vectors and
> > references them with svref. But for me, it looked strange to use
> > svref, when I might at a later stage in programming want to optimize
> > it as an array of fixnums: I would have to replace all the svref by
> > aref then... But maybe (when I interpret Joe Marshall's answer
> > correctly) this is not the case after all?
> 
> The most flexible way to deal with this is via a macro.
> 
> (defmacro fixnum-vector-allocate (size)
>   `(make-array ,size))
> 
> (defmacro fixnum-svref (fixnum-vector index)
>   `(aref ,fixnum-vector ,index))
> 
> Now later on when you want to optimize, just change the macros:
> 
> (defmacro fixnum-vector-allocate (size)
>   `(make-array ,size :element-type 'fixnum))
> 
> (defmacro fixnum-svref (fixnum-vector index)
>   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))

Wouldn't it be better to make these inlined functions instead, to not
break the interface?


Bj�rn
From: Duane Rettig
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <4k6yeyun2.fsf@franz.com>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> Joe Marshall <···@ccs.neu.edu> writes:
> 
> > Christian Hofer <·······@gmx.de> writes:
> > 
> > > Lars Brinkhoff wrote:
> > >> Christian Hofer <·······@gmx.de> writes:
> > >>
> > >>>how do you create a vector of fixnums? The most natural solution seems
> > >>>to be using a simple vector.
> > >>         (let ((v (vector 1 2 3)))
> > >>
> > > [snip]
> > > Sorry for my bad English. 
> > 
> > Don't worry about that, we focus on bad Lisp. 
> > 
> > > My problem was not so much, how I can do it, but how it is normally
> > > done. I see in Graham's ACL, that he uses simple vectors and
> > > references them with svref. But for me, it looked strange to use
> > > svref, when I might at a later stage in programming want to optimize
> > > it as an array of fixnums: I would have to replace all the svref by
> > > aref then... But maybe (when I interpret Joe Marshall's answer
> > > correctly) this is not the case after all?
> > 
> > The most flexible way to deal with this is via a macro.
> > 
> > (defmacro fixnum-vector-allocate (size)
> >   `(make-array ,size))
> > 
> > (defmacro fixnum-svref (fixnum-vector index)
> >   `(aref ,fixnum-vector ,index))
> > 
> > Now later on when you want to optimize, just change the macros:
> > 
> > (defmacro fixnum-vector-allocate (size)
> >   `(make-array ,size :element-type 'fixnum))
> > 
> > (defmacro fixnum-svref (fixnum-vector index)
> >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> 
> Wouldn't it be better to make these inlined functions instead, to not
> break the interface?

You imply that Joe's solution breaks an interface.  Why?

-- 
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   
From: Björn Lindberg
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <hcsfz92ulhj.fsf@knatte.nada.kth.se>
Duane Rettig <·····@franz.com> writes:

> ·······@nada.kth.se (Bj�rn Lindberg) writes:
> 
> > Joe Marshall <···@ccs.neu.edu> writes:
> > 
> > > Christian Hofer <·······@gmx.de> writes:
> > > 
> > > > Lars Brinkhoff wrote:
> > > >> Christian Hofer <·······@gmx.de> writes:
> > > >>
> > > >>>how do you create a vector of fixnums? The most natural solution seems
> > > >>>to be using a simple vector.
> > > >>         (let ((v (vector 1 2 3)))
> > > >>
> > > > [snip]
> > > > Sorry for my bad English. 
> > > 
> > > Don't worry about that, we focus on bad Lisp. 
> > > 
> > > > My problem was not so much, how I can do it, but how it is normally
> > > > done. I see in Graham's ACL, that he uses simple vectors and
> > > > references them with svref. But for me, it looked strange to use
> > > > svref, when I might at a later stage in programming want to optimize
> > > > it as an array of fixnums: I would have to replace all the svref by
> > > > aref then... But maybe (when I interpret Joe Marshall's answer
> > > > correctly) this is not the case after all?
> > > 
> > > The most flexible way to deal with this is via a macro.
> > > 
> > > (defmacro fixnum-vector-allocate (size)
> > >   `(make-array ,size))
> > > 
> > > (defmacro fixnum-svref (fixnum-vector index)
> > >   `(aref ,fixnum-vector ,index))
> > > 
> > > Now later on when you want to optimize, just change the macros:
> > > 
> > > (defmacro fixnum-vector-allocate (size)
> > >   `(make-array ,size :element-type 'fixnum))
> > > 
> > > (defmacro fixnum-svref (fixnum-vector index)
> > >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> > 
> > Wouldn't it be better to make these inlined functions instead, to not
> > break the interface?
> 
> You imply that Joe's solution breaks an interface.  Why?

The macro-wrapped operators are functions (MAKE-ARRAY & AREF). Since
functions and macros behave differently in some ways, you can regard
the functionness of the operators as being part of the
interface. Another person reading the code could reasonably expect the
operator FIXNUM-SVREF to be a function, thus expecting another
interface than the one provided.

If making them inline functions would make them perform worse than the
macros, macros are probably the better choice, since the whole point
of the wrapping is optimization benefits.


Bj�rn
From: Duane Rettig
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <4fz92yq75.fsf@franz.com>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > ·······@nada.kth.se (Bj�rn Lindberg) writes:
> > 
> > > Joe Marshall <···@ccs.neu.edu> writes:
> > > 
> > > > The most flexible way to deal with this is via a macro.
> > > > 
> > > > (defmacro fixnum-vector-allocate (size)
> > > >   `(make-array ,size))
> > > > 
> > > > (defmacro fixnum-svref (fixnum-vector index)
> > > >   `(aref ,fixnum-vector ,index))
> > > > 
> > > > Now later on when you want to optimize, just change the macros:
> > > > 
> > > > (defmacro fixnum-vector-allocate (size)
> > > >   `(make-array ,size :element-type 'fixnum))
> > > > 
> > > > (defmacro fixnum-svref (fixnum-vector index)
> > > >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> > > 
> > > Wouldn't it be better to make these inlined functions instead, to not
> > > break the interface?
> > 
> > You imply that Joe's solution breaks an interface.  Why?
> 
> The macro-wrapped operators are functions (MAKE-ARRAY & AREF). Since
> functions and macros behave differently in some ways, you can regard
> the functionness of the operators as being part of the
> interface.

I recommend against this kind of thinking for the most part, and
especially in the example that Joe gave above.  Macros are an
amazing feature of Lisp, and it is important to understand the
power that macros give to Common Lisp, and in fact we have been
exploring and rediscovering this power during the past year or
so on this newsgroup.  But it is also important to note that one
of the most powerful features of Lisp's macros is that they can
in fact _look_ like functions, and for the most part can be
substituted for functions as the implementor desires.

But let's first look at how macros and functions are different,
especially in the areas we have been discussing in c.l.l:

 1. Macros don't evaluate their arguments.  Yes, this is true,
but in most situations their expansions cause evaluations to
occur.  Most of the time, one _wants_ the argument to a macro to
eventually be evaluated, except for situations where the value
is a manifest constant, such as the name which a defining form
defines [e.g. in (defmacro def-foo (name ...)), I would expect
name to be treated as a manifest constant and its value not be
evaluated].

 2. Macros (and special-operators) can't be funcalled.  This
has been explored very little in c.l.l, except to bemoan the fact
that AND and OR cannot be given to APPLY or FUNCALL.  Do you know
the reasonings behind this?  As one example, suppose you looked
at the original interface, the AREF above, which _is_ a function,
and you used the fact that it was a function and thus did a funcall
on it.  Then when you lose big due to the added overhead in calling
the actual function, rather than allowing the compiler to optimize
it away to a single instruction, don't tell me I didn't warn you...

 3. Functions are opaque.  Macros supply the user of the
macro with insight into how the interface is implemented.  This
is useful in situations where the implementation is complex,
such as the eval-when behaviors of a defining form.  But sometimes
the implementor doesn't want the user to see the implementation,
and so he uses a function.  Incidentally, a compiler-macro supplied
with a function is a much more open than a function which has been
declared inline - the latter is still opaque (i.e. there is no
standard way to get the implementation from an inline-declared
function, whereas a compiler-macro can be macroexpanded to see its
implementation (assuming it is the implementing the same interface,
as it should do).

There may be others, but off the top of my head, these are the
most important differences.  In all other respects (other than
those I may have missed) functions and macros can be the same.
And in Joe's example above, they are - the macros expand to
forms which evaluate each of their arguments once, in the
correct order, and the behaviors are well-defined and documnetable.

> Another person reading the code could reasonably expect the
> operator FIXNUM-SVREF to be a function, thus expecting another
> interface than the one provided.

It is unwise to assume that an operator is anything but an operator,
unless it is explicitly described as a function or macro in its
documentation.  In a well-designed interface, it will hardly matter
anyway, in most cases.  For example, Joe's interface can easily be
implemented as a set of functions, period.  Not very efficient, and
such an implementaion interface would not be likely to sell, but
also implied in this argument is the fact that a programmer is not
likely to funcall fixnum-svref anyway, for the same efficiency
reasons as they are not likely to want the interface to _be_
functions.

-- 
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   
From: Björn Lindberg
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <hcsoenojtor.fsf@tjatte.nada.kth.se>
Duane Rettig <·····@franz.com> writes:

> ·······@nada.kth.se (Bj�rn Lindberg) writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > ·······@nada.kth.se (Bj�rn Lindberg) writes:
> > > 
> > > > Joe Marshall <···@ccs.neu.edu> writes:
> > > > 
> > > > > The most flexible way to deal with this is via a macro.
> > > > > 
> > > > > (defmacro fixnum-vector-allocate (size)
> > > > >   `(make-array ,size))
> > > > > 
> > > > > (defmacro fixnum-svref (fixnum-vector index)
> > > > >   `(aref ,fixnum-vector ,index))
> > > > > 
> > > > > Now later on when you want to optimize, just change the macros:
> > > > > 
> > > > > (defmacro fixnum-vector-allocate (size)
> > > > >   `(make-array ,size :element-type 'fixnum))
> > > > > 
> > > > > (defmacro fixnum-svref (fixnum-vector index)
> > > > >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> > > > 
> > > > Wouldn't it be better to make these inlined functions instead, to not
> > > > break the interface?
> > > 
> > > You imply that Joe's solution breaks an interface.  Why?
> > 
> > The macro-wrapped operators are functions (MAKE-ARRAY & AREF). Since
> > functions and macros behave differently in some ways, you can regard
> > the functionness of the operators as being part of the
> > interface.
> 
> I recommend against this kind of thinking for the most part, and
> especially in the example that Joe gave above.  Macros are an
> amazing feature of Lisp, and it is important to understand the
> power that macros give to Common Lisp, and in fact we have been
> exploring and rediscovering this power during the past year or
> so on this newsgroup.  But it is also important to note that one
> of the most powerful features of Lisp's macros is that they can
> in fact _look_ like functions, and for the most part can be
> substituted for functions as the implementor desires.

Ok, I agree that this particular case is one where the macro variant
is almost as good as using inlined functions (or better, when using a
compiler which is not able to inline the functions). But do you really
disagree that the property of an operator of being a function or a
macro is part of the interface in some cases? I am thinking of when
one would like to pass the operator to a higher order function for
instance. We recently had a thread where arguments were put forth for
why the function/macro distinction can be considered part of the
interface.

> But let's first look at how macros and functions are different,
> especially in the areas we have been discussing in c.l.l:
> 
>  1. Macros don't evaluate their arguments.  Yes, this is true,
> but in most situations their expansions cause evaluations to
> occur.  Most of the time, one _wants_ the argument to a macro to
> eventually be evaluated, except for situations where the value
> is a manifest constant, such as the name which a defining form
> defines [e.g. in (defmacro def-foo (name ...)), I would expect
> name to be treated as a manifest constant and its value not be
> evaluated].
> 
>  2. Macros (and special-operators) can't be funcalled.  This
> has been explored very little in c.l.l, except to bemoan the fact
> that AND and OR cannot be given to APPLY or FUNCALL.  Do you know
> the reasonings behind this?  As one example, suppose you looked
> at the original interface, the AREF above, which _is_ a function,
> and you used the fact that it was a function and thus did a funcall
> on it.  Then when you lose big due to the added overhead in calling
> the actual function, rather than allowing the compiler to optimize
> it away to a single instruction, don't tell me I didn't warn you...
> 
>  3. Functions are opaque.  Macros supply the user of the
> macro with insight into how the interface is implemented.  This
> is useful in situations where the implementation is complex,
> such as the eval-when behaviors of a defining form.  But sometimes
> the implementor doesn't want the user to see the implementation,
> and so he uses a function.  Incidentally, a compiler-macro supplied
> with a function is a much more open than a function which has been
> declared inline - the latter is still opaque (i.e. there is no
> standard way to get the implementation from an inline-declared
> function, whereas a compiler-macro can be macroexpanded to see its
> implementation (assuming it is the implementing the same interface,
> as it should do).
> 
> There may be others, but off the top of my head, these are the
> most important differences.  In all other respects (other than
> those I may have missed) functions and macros can be the same.
> And in Joe's example above, they are - the macros expand to
> forms which evaluate each of their arguments once, in the
> correct order, and the behaviors are well-defined and documnetable.

Yes, the only show their macro nature in situations like thos in (2)
above.

> > Another person reading the code could reasonably expect the
> > operator FIXNUM-SVREF to be a function, thus expecting another
> > interface than the one provided.
> 
> It is unwise to assume that an operator is anything but an operator,
> unless it is explicitly described as a function or macro in its
> documentation.  In a well-designed interface, it will hardly matter
> anyway, in most cases.  For example, Joe's interface can easily be
> implemented as a set of functions, period.  Not very efficient, and
> such an implementaion interface would not be likely to sell, but
> also implied in this argument is the fact that a programmer is not
> likely to funcall fixnum-svref anyway, for the same efficiency
> reasons as they are not likely to want the interface to _be_
> functions.

I see what you mean. Good point.


Bj�rn
From: Christian Hofer
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <m2vfhxrdj6.fsf@chr-iBook.local>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > ·······@nada.kth.se (Bj�rn Lindberg) writes:
> > 
> > > Joe Marshall <···@ccs.neu.edu> writes:
> > > > The most flexible way to deal with this is via a macro.
> > > > 
> > > > (defmacro fixnum-vector-allocate (size)
> > > >   `(make-array ,size))
> > > > 
> > > > (defmacro fixnum-svref (fixnum-vector index)
> > > >   `(aref ,fixnum-vector ,index))
> > > > 
> > > > Now later on when you want to optimize, just change the macros:
> > > > 
> > > > (defmacro fixnum-vector-allocate (size)
> > > >   `(make-array ,size :element-type 'fixnum))
> > > > 
> > > > (defmacro fixnum-svref (fixnum-vector index)
> > > >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> > > 
> > > Wouldn't it be better to make these inlined functions instead, to not
> > > break the interface?
> > 
> > You imply that Joe's solution breaks an interface.  Why?
> 
> The macro-wrapped operators are functions (MAKE-ARRAY & AREF). Since
> functions and macros behave differently in some ways, you can regard
> the functionness of the operators as being part of the
> interface. Another person reading the code could reasonably expect the
> operator FIXNUM-SVREF to be a function, thus expecting another
> interface than the one provided.

I do not understand this. Shouldn't the macro be expanded to a
function and then behave exactly like it? By that, I could use it as a
parameter in another function...

Chris
From: Björn Lindberg
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <hcsk6ycjtlv.fsf@tjatte.nada.kth.se>
Christian Hofer <·······@gmx.de> writes:

> ·······@nada.kth.se (Bj�rn Lindberg) writes:
> 
> > Duane Rettig <·····@franz.com> writes:
> > 
> > > ·······@nada.kth.se (Bj�rn Lindberg) writes:
> > > 
> > > > Joe Marshall <···@ccs.neu.edu> writes:
> > > > > The most flexible way to deal with this is via a macro.
> > > > > 
> > > > > (defmacro fixnum-vector-allocate (size)
> > > > >   `(make-array ,size))
> > > > > 
> > > > > (defmacro fixnum-svref (fixnum-vector index)
> > > > >   `(aref ,fixnum-vector ,index))
> > > > > 
> > > > > Now later on when you want to optimize, just change the macros:
> > > > > 
> > > > > (defmacro fixnum-vector-allocate (size)
> > > > >   `(make-array ,size :element-type 'fixnum))
> > > > > 
> > > > > (defmacro fixnum-svref (fixnum-vector index)
> > > > >   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
> > > > 
> > > > Wouldn't it be better to make these inlined functions instead, to not
> > > > break the interface?
> > > 
> > > You imply that Joe's solution breaks an interface.  Why?
> > 
> > The macro-wrapped operators are functions (MAKE-ARRAY & AREF). Since
> > functions and macros behave differently in some ways, you can regard
> > the functionness of the operators as being part of the
> > interface. Another person reading the code could reasonably expect the
> > operator FIXNUM-SVREF to be a function, thus expecting another
> > interface than the one provided.
> 
> I do not understand this. Shouldn't the macro be expanded to a
> function and then behave exactly like it? By that, I could use it as a
> parameter in another function...

Yes, but you cannot funcall the macro, so you cannot eg. pass it as an
argument to a mapping function.

  (mapcar #'fixnum-svref ... ...)

will not work.


Bj�rn
From: Joe Marshall
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <fz92i0vn.fsf@ccs.neu.edu>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> Joe Marshall <···@ccs.neu.edu> writes:
>> 
>> The most flexible way to deal with this is via a macro.
>> 
>> (defmacro fixnum-vector-allocate (size)
>>   `(make-array ,size))
>> 
>> (defmacro fixnum-svref (fixnum-vector index)
>>   `(aref ,fixnum-vector ,index))
>> 
>> Now later on when you want to optimize, just change the macros:
>> 
>> (defmacro fixnum-vector-allocate (size)
>>   `(make-array ,size :element-type 'fixnum))
>> 
>> (defmacro fixnum-svref (fixnum-vector index)
>>   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
>
> Wouldn't it be better to make these inlined functions instead, to not
> break the interface?

Probably.  Not every implementation obeys the `inline' declaration,
though.
From: Christophe Rhodes
Subject: Re: simple vector versus simple array
Date: 
Message-ID: <sq3c52t83l.fsf@cam.ac.uk>
Joe Marshall <···@ccs.neu.edu> writes:

> ·······@nada.kth.se (Björn Lindberg) writes:
>
>> Joe Marshall <···@ccs.neu.edu> writes:
>>> (defmacro fixnum-svref (fixnum-vector index)
>>>   `(the fixnum (aref (the (array fixnum (*)) ,fixnum-vector) ,index)))
>>
>> Wouldn't it be better to make these inlined functions instead, to not
>> break the interface?
>
> Probably.  Not every implementation obeys the `inline' declaration,
> though.

In addition to providing an inline function, for the benefit of such
misbehaving implementations, one can provide a compiler macro.  If the
implementation is doubly misbehaving (bad implementation; no cookie!),
then, well, suffer.

[ in case anyone is in any doubt: it is perfectly legal for an
  implementation to ignore both inline declarations and compiler
  macros.  Not all misbehaviour is illegal, as exemplified in today's
  society. ]

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)