[comp.lang.lisp] pointers in Lisp

artzi@cpsvax.cps.msu.edu (Ytshak Artzi - CPS) (02/03/89)

Problem:

      I need to implement (in Common Lisp) a structure with pointers. I will
use Pascal jargon to best describe it:

           element : record
                        data : some_type
                        p1   :pointer_to_element
                        :
                        :
                        pk   :pointer_to_element
                     end;

REM: k is a constant chosen (by me) not bigger than 10.

Catch: the number of pointers 'allocated' to each variable MUST be
       random at the beginning of the program. Any suggestions will be
       appreciated . I wish to be able to (randomly) create structures
       with 3, 5 or 9 pointers for example.
          Please don't propose an array of pointers with a flag randomly
       chosen between 1 and 10.

     Itzik.

edward@ucbarpa.Berkeley.EDU (Edward Wang) (02/04/89)

In article <1710@cps3xx.UUCP> artzi@cpsvax.cps.msu.edu (Ytshak Artzi - CPS) writes:
<      I need to implement (in Common Lisp) a structure with pointers. I will
<use Pascal jargon to best describe it:
<
<           element : record
<                        data : some_type
<                        p1   :pointer_to_element
<                        :
<                        :
<                        pk   :pointer_to_element
<                     end;
<
<REM: k is a constant chosen (by me) not bigger than 10.
<
<. . .
<          Please don't propose an array of pointers with a flag randomly
<       chosen between 1 and 10.

And may we ask why not?

How about not having a size field at all but use array-dimension
when you need to know?

welch@tut.cis.ohio-state.edu (Arun Welch) (02/04/89)

In article <1710@cps3xx.UUCP>, artzi@cpsvax.cps.msu.edu (Ytshak Artzi - CPS) writes:
> Problem:
> 
>       I need to implement (in Common Lisp) a structure with pointers. I will
> use Pascal jargon to best describe it:
> 
>            element : record
>                         data : some_type
>                         p1   :pointer_to_element
>                         :
>                         :
>                         pk   :pointer_to_element
>                      end;
> 

Seeing as how this is lisp, why dont you just use a list?  Unless your CL is 
incredibly inefficient, mapping over a list of 10 elements is gonna be plenty
fast, and you'll probably take up less storage than the array.

...arun

----------------------------------------------------------------------------
Arun Welch
Lisp Systems Programmer, Lab for AI Research, Ohio State University
welch@cis.ohio-state.edu

raymond@ptolemy.arc.nasa.gov (Eric A. Raymond) (02/04/89)

In article <27884@ucbvax.BERKELEY.EDU> edward@ucbarpa.Berkeley.EDU.UUCP (Edward Wang) writes:
>In article <1710@cps3xx.UUCP> artzi@cpsvax.cps.msu.edu (Ytshak Artzi - CPS) writes:
><      I need to implement (in Common Lisp) a structure with pointers. I will
><          Please don't propose an array of pointers with a flag randomly
><       chosen between 1 and 10.
>
>How about not having a size field at all but use array-dimension
>when you need to know?

What about those things called lists?

By the way, the beauty of Lisp is that you don't have to pre-type
your variables.  For example in

  (defstruct thing
     component1
     component2
     ...)

you can setq anything (i.e. atom, list, array, structure) to any of the
components.  

Don't worry about pointers in Lisp.  It's not really that important a
concept as it is in C or Pascal.  The language shields you from the hassle
(and in only a few instances does this really get in the way).
-- 
Eric A. Raymond  (raymond@pluto.arc.nasa.gov)
Nothing left to do but :-) :-) :-)

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (02/06/89)

In article <33722@tut.cis.ohio-state.edu>, welch@tut (Arun Welch) writes:
>>       I need to implement (in Common Lisp) a structure with pointers. I will
>> use Pascal jargon to best describe it:
>> 
>>            element : record
>>                         data : some_type
>>                         p1   :pointer_to_element
>>                         :
>>                         :
>>                         pk   :pointer_to_element
>>                      end;
>> 
>
>Seeing as how this is lisp, why dont you just use a list?  Unless your CL is 
>incredibly inefficient, mapping over a list of 10 elements is gonna be plenty
>fast, and you'll probably take up less storage than the array.

A variable-sized array will be both faster and smaller than a list.  (Unless
you're using a CDR-coded LISP on a LM, in which case they're the same.)


Bruce Krulwich

weinrich@lightning.rutgers.edu (Timothy M. Weinrich) (02/08/89)

	From: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich)
	Subject: Re: pointers in Lisp
	Date: 5 Feb 89 18:21:47 GMT
	A variable-sized array will be both faster and smaller than a
	list.  (Unless you're using a CDR-coded LISP on a LM, in which
	case they're the same.)

   Are you taking into consideration (for example) the bounds-checking
that would almost certainly get compiled into every array reference?

   Twinerik

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (02/09/89)

In article <Feb.7.11.41.26.1989.517@lightning.rutgers.edu>, weinrich@lightning
(Timothy M. Weinrich) writes:
>
>	A variable-sized array will be both faster and smaller than a
>	list.  (Unless you're using a CDR-coded LISP on a LM, in which
>	case they're the same.)
>
>   Are you taking into consideration (for example) the bounds-checking
>that would almost certainly get compiled into every array reference?

You're right, I wasn't.  People who have sent me mail have said they
find the breakeven point to be around 5-10 elements, so if your sequence
is longer then you should use an array, otherwise a list may be better.


Bruce

barmar@think.COM (Barry Margolin) (02/09/89)

In article <Feb.7.11.41.26.1989.517@lightning.rutgers.edu> weinrich@lightning.rutgers.edu (Timothy M. Weinrich) writes:
>	From: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich)
>	A variable-sized array will be both faster and smaller than a
>	list.  (Unless you're using a CDR-coded LISP on a LM, in which
>	case they're the same.)

Note that Lispms aren't the only Lisps with CDR-coding.  I believe
that a number of Lisps for conventional processors do CDR-coding these
days.  It's a time/space tradeoff in these cases.

While you are correct that an array and a CDR-coded list are about the
same size (an array may have an extra word or two of header),
accessing an arbitrary element of a CDR-coded list is NOT as fast as
accessing an array element.  Even with CDR-coding, accessing the Nth
element of a list is still O(N), while it is O(1) for an array.

Actually, you could make CDR-coded list accesses as fast as arrays if
there were a field in each list element that specifies how long the
chain of CDR-NEXT elements following it is; if N is less than this
then array-style access can be used instead of sequential access.  I
think this scheme would require too many bits, because it needs to be
useful for long lists or it isn't worthwhile (perhaps some low-order
bits could be dropped and the result shifted, i.e. the field could
specify how many multiples of 32 or 64 CDR-NEXT elements follow).
Also, it makes RPLACD of a CDR-NEXT element really slow, because it
must go back and update all the predecessors.

>   Are you taking into consideration (for example) the bounds-checking
>that would almost certainly get compiled into every array reference?

On Lispms the bounds checking takes no time because it occurs in
parallel with the data access.  On conventional machines the compiler
can usually be told not to generate bounds checking, usually by the
use of OPTIMIZE proclamations and declarations.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

barmar@think.COM (Barry Margolin) (02/09/89)

In article <50041@yale-celray.yale.UUCP> Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) writes:
>You're right, I wasn't.  People who have sent me mail have said they
>find the breakeven point to be around 5-10 elements, so if your sequence
>is longer then you should use an array, otherwise a list may be better.

Be careful with such general statements.  You didn't say what Lisp
implementations, what architectures, etc.  I just tried some
experiements on my Symbolics 3640 running Genera 7.2, and AREF is
faster than NTH except in one insignificant case.  My test was:

(defun test (index repetitions)
  (let ((length (1+ index)))
    (let ((array (make-array length))
	  (list (make-list length)))
      (without-interrupts
	(dotimes (i repetitions)
	  ;; nothing -- to determine loop overhead
	  ))
      (without-interrupts
	(dotimes (i repetitions)
	  (aref array index)))
      (without-interrupts
	(dotimes (i repetitions)
	  (nth index list))))))

The results were that an AREF takes about 2.5 microseconds, and NTH
takes about 13+4N microseconds.  I was able to reduce the 13 to 8 by
removing the argument checking from NTH, and got it down to 6 by
making it compile inline instead of as a function call.  But AREF is
still faster.

The only time I managed to get a list access to be faster was when the
first argument to NTH was the constant 0.  The compiler special-cases
NTH when the first argument is a constant from 0 to 9 and generates
the appropriate series of CAR and CDR instructions.  In these cases,
NTH 0 (i.e. CAR) takes about 1 microsecond, and NTH 1-9 takes about
2.5+.5N microseconds, putting AREF between NTH 0 and NTH 1.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

shebs@Apple.COM (Stanley Todd Shebs) (02/10/89)

In article <36238@think.UUCP> barmar@kulla.think.com.UUCP (Barry Margolin) writes:
>Note that Lispms aren't the only Lisps with CDR-coding.  I believe
>that a number of Lisps for conventional processors do CDR-coding these
>days.  It's a time/space tradeoff in these cases.

Whoa!  Which ones do you know for sure do cdr-coding??  I've not seen any
myself, even after an extensive survey of systems, which wasn't surprising
because you lose big if you don't have hardware support for forwarding ptrs...

							stan shebs
							shebs@apple.com

barmar@think.COM (Barry Margolin) (02/11/89)

In article <624@internal.Apple.COM> shebs@Apple.COM (Stanley Todd Shebs) writes:
>In article <36238@think.UUCP> barmar@kulla.think.com.UUCP (Barry Margolin) writes:
>>Note that Lispms aren't the only Lisps with CDR-coding.  I believe
>>that a number of Lisps for conventional processors do CDR-coding these
>>days.  It's a time/space tradeoff in these cases.
>Whoa!  Which ones do you know for sure do cdr-coding??  I've not seen any
>myself, even after an extensive survey of systems, which wasn't surprising
>because you lose big if you don't have hardware support for forwarding ptrs...

No, I don't know for sure.  I thought I'd heard people from Lucid
and/or Franz mention such things at X3J13 meetings, but perhaps I am
either mistaken or I misunderstood.  Maybe they only use CDR-coding in
very restricted cases (if you never REPLACD in a CDR-coded list, you
don't need forwarding pointers, so maybe there is a declaration that
specifies this).

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

alex@umbc3.UMBC.EDU (Alex S. Crain) (02/11/89)

	Um, what exactly is a CRD-coded list?
-- 
					:alex
Alex Crain
Systems Programmer			alex@umbc3.umbc.edu
Univ Md Baltimore County		nerwin!alex@umbc3.umbc.edu (NEW DOMAIN)

barmar@think.COM (Barry Margolin) (02/13/89)

In article <1648@umbc3.UMBC.EDU> alex@umbc3.umbc.edu.UMBC.EDU (Alex S. Crain) writes:
>	Um, what exactly is a CRD-coded list?

CDR-coding is a technique for reducing the storage taken up by lists.
Cons cells, which are the normal building blocks of lists, are more
general than is frequently needed; they can be used to build arbitrary
trees, but many Lisp data structures are simply linear lists, and
don't take advantage of this generality.

In CDR coding, each list element is represented using a single CAR
pointer plus a two-bit CDR-code field.  The CDR-code indicates how to
compute the CDR of the list, and has three possible values:
CDR-NORMAL, CDR-NEXT, and CDR-NIL.  CDR-NORMAL indicates that the word
is the CAR of a normal cons cell, so the following word contains a
pointer to the cdr.  CDR-NEXT means that the following word IS the
cdr.  And CDR-NIL means that this word was the last list element, and
the cdr is implicitly NIL.

A list where all the elements are CDR-NEXT (except, of course, for the
last, which is CDR-NIL) will take up half as much storage as one that
is all CDR-NORMAL.  However, CDR-coding in general requires some
additional architectural features, most importantly invisible
pointers.  If you RPLACD a cons that is CDR-NEXT or CDR-NIL there is
no cdr cell to store into.  Instead, you allocate a new CDR-NORMAL
cons, copy the original car to the new one's car, and replace the
original car cell with an invisible pointer to the new cons.  An
invisible pointer is a word that automatically gets dereferenced when
you try to read its contents.  Invisible pointers require hardware
support to prevent an enormous performance hit.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

jeff@aiai.ed.ac.uk (Jeff Dalton) (02/17/89)

In article <624@internal.Apple.COM> shebs@Apple.COM (Stanley Todd Shebs)
writes: 
  In article <36238@think.UUCP> barmar@kulla.think.com.UUCP (Barry
  Margolin) writes:
    Note that Lispms aren't the only Lisps with CDR-coding.  I believe
    that a number of Lisps for conventional processors do CDR-coding these
    days.  It's a time/space tradeoff in these cases.
  Whoa!  Which ones do you know for sure do cdr-coding??  I've not seen
  any myself, even after an extensive survey of systems, which wasn't
  surprising because you lose big if you don't have hardware support for
  forwarding ptrs...

Eclisp, a Lisp for the Data General Eclipse computers, used internally
at Data General, used cdr-coding.  It may have exploited a "go inderect"
that could be placed in a location (if indeed the Eclipse had such
bits).  "Conventional processors" can cover quite a variety of
machines.

Jeff Dalton,                      JANET: J.Dalton@uk.ac.ed             
AI Applications Institute,        ARPA:  J.Dalton%uk.ac.ed@nss.cs.ucl.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton