D-Lists

  • Follow


There are two common structures for associative maps in Lisp, A-Lists 
and P-Lists.  A-Lists are structured like so:

((key . value) (key . value) ...)

while P-Lists are structured like so:

(key value key value ...)

Both are equally efficient in terms of storage and search times.  ALists 
have a slight advantage over PLists when used as models of lambda 
bindings because popping a binding requires only one CDR operations 
whereas a PList requires two.  (Note that I am talking about PLists in 
the abstract here, without the additional constraints imposed on them by 
e.g. Common Lisp, which requires a P-List to have unique keys.)

There is a third representation of an abstract associative map, which 
I've never seen mentioned before.  But it is so obvious I can't believe 
that the idea is original with me.  For the moment I've dubbed them 
DLists.  They look like this:

((key1 key2 ... keyN) value1 value2 ... valueN)

DLists are just as efficient as ALists and PLists for all common 
operations, but they have several advantages over either ALists or 
PLists:

1.  The empty DList is not (), it's (()).  This means that you can push 
new bindings onto a DList without having to special-case NIL like you do 
with ALists or Plists.

2.  When using a DList as a model of a lexical environment, the keys and 
values are cleanly separated, so you can compile a lexical access simply 
by looking up the position of the key in the CAR of the DList, after 
which you can discard the CAR of the DList with no loss of 
functionality.  In other words, (deref dlist key) is equivalent to (nth 
(position key (car dlist)) (cdr dlist)), and (position key (car dlist)) 
is a compile-time constant.

3.  It is trivial to replace the CAR and the CDR of a DList with vectors 
(optionally adjustable vectors with fill pointers, though for the common 
use case of modeling lambda bindings this would not be necessary), in 
which case dereferencing constant keys can be done in amortized O(1) 
time.  This transformation is not possible with ALists or PLists.  Of 
course, it is possible to dereference constant keys for ALists and 
PLists in amortized O(1) time by keeping a reference to the value cell 
itself, but separating the steps so that there is a tangible 
intermediate result that is an integer offset into a value vector I 
believe has pedagogical value when teaching students how closures are 
compiled.

4.  Multiple D-Lists can share the same key list, making D-Lists more 
space efficient (by a factor asymptotically approaching 2) for the 
common use case of modeling lexical environments that get instantiated 
multiple times.

But all that is neither here nor there, because my actual question is: 
has all this been thought of before?  I can't imagine that it hasn't 
been, but I've never seen it in any Lisp text.  If there's literature on 
this, can someone point me to a reference?  Do these structures have an 
actual name?

Thanks,
rg
0
Reply rNOSPAMon (1854) 7/26/2009 5:39:22 PM

Ron Garret <rNOSPAMon@flownet.com> writes:

> Common Lisp [...] requires a P-List to have unique keys.

In the CL standard, the glossary entry for "property list", the
specification of GET, and the specification of GETF contradict this
notion. Is there a passage that supports it?

Zach
0
Reply xach (862) 7/26/2009 6:04:53 PM


In article <m3ws5vb9ru.fsf@unnamed.xach.com>,
 Zach Beane <xach@xach.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > Common Lisp [...] requires a P-List to have unique keys.
> 
> In the CL standard, the glossary entry for "property list", the
> specification of GET, and the specification of GETF contradict this
> notion. Is there a passage that supports it?
> 
> Zach

My mistake.  It's emacs lisp that has this requirement, not CL.  
(Reference: http://www.emacswiki.org/emacs/AlistVsPlist :
"In a plist, each key must be distinct.")

rg
0
Reply rNOSPAMon (1854) 7/26/2009 6:13:36 PM

On Jul 26, 10:39=A0am, Ron Garret <rNOSPA...@flownet.com> wrote:
>
> 4. =A0Multiple D-Lists can share the same key list

For an extreme example of where this can be taken, check out my
"dynamic tuples":

http://common-lisp.net/project/fset/

Look in file `Code/tuples.lisp'.

Not only do multiple tuples share a single key vector, there's a cute
key-reordering feature that pulls commonly-accessed keys toward the
beginning of the vector.  (The key vector and value vector are thus
not in the same order, but the key vector has indices into the value
vector.)

-- Scott
0
Reply FSet.SLB (346) 7/26/2009 6:32:24 PM

Ron Garret <rNOSPAMon@flownet.com> writes:

> 1.  The empty DList is not (), it's (()).  This means that you can push 
> new bindings onto a DList without having to special-case NIL like you do 
> with ALists or Plists.

What special case did you have in mind?

Zach
0
Reply xach (862) 7/26/2009 7:57:19 PM

In article <m3skgjb4kg.fsf@unnamed.xach.com>,
 Zach Beane <xach@xach.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > 1.  The empty DList is not (), it's (()).  This means that you can push 
> > new bindings onto a DList without having to special-case NIL like you do 
> > with ALists or Plists.
> 
> What special case did you have in mind?
> 
> Zach

If we want to treat associative maps as objects with state independent 
of the places where they are stored, we can do e.g. this with DLists:

(defun add-binding-to-dlist (key value dlist)
  (push key (car dlist))
  (push value (cdr dlist))
  dlist)

which works thusly:

? (setf dlist (list nil))  ; Empty DList
(NIL)
? (add-binding-to-dlist 'k1 'v1 dlist)
((K1) V1)
? dlist
((K1) V1)
? 

If we try to do the analogous thing with ALists or PLists it's not quite 
possible.  We can do e.g. this:

(defun add-binding-to-alist (key value alist)
  (let ((temp (car alist)))
    (rplaca alist (cons key value))
    (rplacd alist (cons temp (cdr alist)))
    alist))

which works as long as the list isn't empty:

? (setf alist (list '(k1 . v1)))
((K1 . V1))
? (add-binding-to-alist 'k2 'v2 alist)
((K2 . V2) (K1 . V1))
? alist
((K2 . V2) (K1 . V1))

but fails if there are no bindings:

? (setf alist nil)
NIL
? (add-binding-to-alist 'k2 'v2 alist)
> Error: value NIL is not of the expected type CONS.

In other words, all DLists are of type PAIR, even the empty DList.  All 
ALists and PLists are of type PAIR *except* the empty AList/PList, which 
is of type NULL.

rg
0
Reply rNOSPAMon (1854) 7/26/2009 8:23:50 PM

In article 
<19e3dc45-037b-4f25-aed6-89f09ddbcba6@d4g2000prc.googlegroups.com>,
 Scott Burson <FSet.SLB@gmail.com> wrote:

> On Jul 26, 10:39�am, Ron Garret <rNOSPA...@flownet.com> wrote:
> >
> > 4. �Multiple D-Lists can share the same key list
> 
> For an extreme example of where this can be taken, check out my
> "dynamic tuples":
> 
> http://common-lisp.net/project/fset/
> 
> Look in file `Code/tuples.lisp'.
> 
> Not only do multiple tuples share a single key vector, there's a cute
> key-reordering feature that pulls commonly-accessed keys toward the
> beginning of the vector.  (The key vector and value vector are thus
> not in the same order, but the key vector has indices into the value
> vector.)
> 
> -- Scott

Spiffy!  Thanks for the pointer.

rg
0
Reply rNOSPAMon (1854) 7/26/2009 8:25:29 PM

Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <m3skgjb4kg.fsf@unnamed.xach.com>,
>  Zach Beane <xach@xach.com> wrote:
>
>> Ron Garret <rNOSPAMon@flownet.com> writes:
>> 
>> > 1.  The empty DList is not (), it's (()).  This means that you can push 
>> > new bindings onto a DList without having to special-case NIL like you do 
>> > with ALists or Plists.
>> 
>> What special case did you have in mind?
>> 
>> Zach
>
> If we want to treat associative maps as objects with state independent 
> of the places where they are stored, we can do e.g. this with DLists:

I suppose this "problem" of NIL makes people not use alists/plists like
that, instead non-destructively extending them with ACONS or LIST*.

Zach
0
Reply xach (862) 7/26/2009 8:52:34 PM

On Jul 26, 7:39=A0pm, Ron Garret <rNOSPA...@flownet.com> wrote:
> [...]
> There is a third representation of an abstract associative map, which
> I've never seen mentioned before. =A0But it is so obvious I can't believe
> that the idea is original with me. =A0For the moment I've dubbed them
> DLists. =A0They look like this:
>
> ((key1 key2 ... keyN) value1 value2 ... valueN)
> [...]
> But all that is neither here nor there, because my actual question is:
> has all this been thought of before? =A0I can't imagine that it hasn't
> been, but I've never seen it in any Lisp text. =A0If there's literature o=
n
> this, can someone point me to a reference? =A0Do these structures have an
> actual name?

"Not A-lists"? See note {This ain't A-lists} in
"The Art of the Interpreter of, the Modularity Complex (Parts Zero,
One, and Two)"
( http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf
).


Mattias
0
Reply mattiasn (31) 7/26/2009 9:24:05 PM

In article <m3iqhfb20d.fsf@unnamed.xach.com>,
 Zach Beane <xach@xach.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > In article <m3skgjb4kg.fsf@unnamed.xach.com>,
> >  Zach Beane <xach@xach.com> wrote:
> >
> >> Ron Garret <rNOSPAMon@flownet.com> writes:
> >> 
> >> > 1.  The empty DList is not (), it's (()).  This means that you can push 
> >> > new bindings onto a DList without having to special-case NIL like you do 
> >> > with ALists or Plists.
> >> 
> >> What special case did you have in mind?
> >> 
> >> Zach
> >
> > If we want to treat associative maps as objects with state independent 
> > of the places where they are stored, we can do e.g. this with DLists:
> 
> I suppose this "problem"

I didn't say it was a "problem."  Please don't introduce conflict where 
none exists.

> of NIL makes people not use alists/plists like
> that, instead non-destructively extending them with ACONS or LIST*.

Sometimes, and sometimes it makes them use setf macros to effect 
mutation, which forces them to bind the objects to particular places, 
most notably (but not exclusively) in symbol-plists.  But *if* someone 
wants an associative map that they can treat as a simple mutable object 
they can't use a PList nor an AList.  But they can use a DList.  Note 
that DLists can also be extended functionally as well:

(defun dcons (key value dlist)
  (cons (cons key (car dlist)) (cons value (cdr dlist))))

? (dcons 'k1 'v1 (extend-dlist 'k2 'v2 '(())))
((K1 K2) V1 V2)

rg
0
Reply rNOSPAMon (1854) 7/26/2009 9:37:00 PM

Ron Garret <rNOSPAMon@flownet.com> writes:

>> > If we want to treat associative maps as objects with state independent 
>> > of the places where they are stored, we can do e.g. this with DLists:
>> 
>> I suppose this "problem"
>
> I didn't say it was a "problem."  Please don't introduce conflict where 
> none exists.

If you don't find the special casing of NIL a problem with alists and
plists compared to dlists, it's a little silly to list the absence of a
special case as an advantage of dlists.

Zach
0
Reply xach (862) 7/26/2009 9:55:01 PM

In article <m38wibaz4a.fsf@unnamed.xach.com>,
 Zach Beane <xach@xach.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> >> > If we want to treat associative maps as objects with state independent 
> >> > of the places where they are stored, we can do e.g. this with DLists:
> >> 
> >> I suppose this "problem"
> >
> > I didn't say it was a "problem."  Please don't introduce conflict where 
> > none exists.
> 
> If you don't find the special casing of NIL a problem with alists and
> plists compared to dlists, it's a little silly to list the absence of a
> special case as an advantage of dlists.

I like blue cars.  So if I were to go shopping for a car, a blue car 
would have an advantage over a red one.  I would not say, however, that 
there is therefore a "problem" with red cars.

Analogously, some people like an object-oriented programming style.  For 
such people, DLists offer an advantage over PLists or ALists.  It does 
not follow that PLists and ALists have a "problem."

rg
0
Reply rNOSPAMon (1854) 7/27/2009 1:21:03 AM

Ron Garret wrote:
> For the moment I've dubbed them DLists.  They look like this:
> 
> ((key1 key2 ... keyN) value1 value2 ... valueN)

FWIW, this is similar to the parameter list to PROGV.

- Daniel
0
Reply dherring1 (548) 7/27/2009 1:48:50 AM

Mattias Nilsson  <mattiasn@bredband.net> wrote:
+---------------
| Garret <rNOSPA...@flownet.com> wrote:
| > There is a third representation of an abstract associative map, which
| > I've never seen mentioned before. But it is so obvious I can't believe
| > that the idea is original with me. For the moment I've dubbed them
| > DLists. They look like this:
| >
| > ((key1 key2 ... keyN) value1 value2 ... valueN)
| > [...]
| > But all that is neither here nor there, because my actual question is:
| > has all this been thought of before? I can't imagine that it hasn't
| > been, but I've never seen it in any Lisp text. If there's literature on
| > this, can someone point me to a reference? Do these structures have an
| > actual name?
| 
| "Not A-lists"? See note {This ain't A-lists} in
| "The Art of the Interpreter of, the Modularity Complex (Parts Zero,
| One, and Two)"
| ( http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf ).
+---------------

In addition to that, SICP2 also discusses this version [not at all
surprising, given the 2nd author of AIM-453] for lexical environments
which are a list of "frames", each of which is a cons of a list of
variables and a list of values. See the functions MAKE-FRAME and
EXTEND-ENVIRONMENT in the source file "ch4-mceval.scm" from SICP2.
[Note: SICP1 didn't seem to use this method; compare with "chapter4.code".]

Queinnec also discusses this variation in L.i.S.P., Chapter 1,
Exercise 1.3, with solution code in the source file "chap1d.scm":

    (define (extend env names values)
      (cons (cons names values) env)) 

    (define (lookup id env)
      ...[~15 lines].. )

Also, in "Chapter 6: Fast interpretation" [which has lots of variations
on representations of lexical environments] he includes the option of
making the "values" side be a vector and then dropping the "names" side
entirely at runtime, using only the offsets computed at compile time.

[He also discusses "flat" environments and the need in such environments
to box lexical bindings that are shared, mutated, & escape, but that's
another story...]


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607

0
Reply rpw3 (2294) 7/27/2009 3:21:37 AM

In article <TM6dnZ34lf7cgPDXnZ2dnUVZ_oydnZ2d@speakeasy.net>,
 rpw3@rpw3.org (Rob Warnock) wrote:

> Mattias Nilsson  <mattiasn@bredband.net> wrote:
> +---------------
> | Garret <rNOSPA...@flownet.com> wrote:
> | > There is a third representation of an abstract associative map, which
> | > I've never seen mentioned before. But it is so obvious I can't believe
> | > that the idea is original with me. For the moment I've dubbed them
> | > DLists. They look like this:
> | >
> | > ((key1 key2 ... keyN) value1 value2 ... valueN)
> | > [...]
> | > But all that is neither here nor there, because my actual question is:
> | > has all this been thought of before? I can't imagine that it hasn't
> | > been, but I've never seen it in any Lisp text. If there's literature on
> | > this, can someone point me to a reference? Do these structures have an
> | > actual name?
> | 
> | "Not A-lists"? See note {This ain't A-lists} in
> | "The Art of the Interpreter of, the Modularity Complex (Parts Zero,
> | One, and Two)"
> | ( http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf ).
> +---------------
> 
> In addition to that, SICP2 also discusses this version [not at all
> surprising, given the 2nd author of AIM-453] for lexical environments
> which are a list of "frames", each of which is a cons of a list of
> variables and a list of values. See the functions MAKE-FRAME and
> EXTEND-ENVIRONMENT in the source file "ch4-mceval.scm" from SICP2.
> [Note: SICP1 didn't seem to use this method; compare with "chapter4.code".]
> 
> Queinnec also discusses this variation in L.i.S.P., Chapter 1,
> Exercise 1.3, with solution code in the source file "chap1d.scm":
> 
>     (define (extend env names values)
>       (cons (cons names values) env)) 
> 
>     (define (lookup id env)
>       ...[~15 lines].. )
> 
> Also, in "Chapter 6: Fast interpretation" [which has lots of variations
> on representations of lexical environments] he includes the option of
> making the "values" side be a vector and then dropping the "names" side
> entirely at runtime, using only the offsets computed at compile time.
> 
> [He also discusses "flat" environments and the need in such environments
> to box lexical bindings that are shared, mutated, & escape, but that's
> another story...]

Just what I was looking for.  Thanks!

rg
0
Reply rNOSPAMon (1854) 7/27/2009 3:41:48 AM

In article <rNOSPAMon-7545AD.18210326072009@news.albasani.net>,
 Ron Garret <rNOSPAMon@flownet.com> wrote:

> In article <m38wibaz4a.fsf@unnamed.xach.com>,
>  Zach Beane <xach@xach.com> wrote:
> 
> > Ron Garret <rNOSPAMon@flownet.com> writes:
> > 
> > >> > If we want to treat associative maps as objects with state independent 
> > >> > of the places where they are stored, we can do e.g. this with DLists:
> > >> 
> > >> I suppose this "problem"
> > >
> > > I didn't say it was a "problem."  Please don't introduce conflict where 
> > > none exists.
> > 
> > If you don't find the special casing of NIL a problem with alists and
> > plists compared to dlists, it's a little silly to list the absence of a
> > special case as an advantage of dlists.
> 
> I like blue cars.  So if I were to go shopping for a car, a blue car 
> would have an advantage over a red one.  I would not say, however, that 
> there is therefore a "problem" with red cars.
> 
> Analogously, some people like an object-oriented programming style.  For 
> such people, DLists offer an advantage over PLists or ALists.  It does 
> not follow that PLists and ALists have a "problem."
> 
> rg

All you've done is add a level of indirection.  It's just as easy to do 
that with alists and plists.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
0
Reply barmar (5623) 7/27/2009 12:44:43 PM

In article <barmar-68EA64.08444327072009@news.eternal-september.org>,
 Barry Margolin <barmar@alum.mit.edu> wrote:

> In article <rNOSPAMon-7545AD.18210326072009@news.albasani.net>,
>  Ron Garret <rNOSPAMon@flownet.com> wrote:
> 
> > In article <m38wibaz4a.fsf@unnamed.xach.com>,
> >  Zach Beane <xach@xach.com> wrote:
> > 
> > > Ron Garret <rNOSPAMon@flownet.com> writes:
> > > 
> > > >> > If we want to treat associative maps as objects with state 
> > > >> > independent 
> > > >> > of the places where they are stored, we can do e.g. this with 
> > > >> > DLists:
> > > >> 
> > > >> I suppose this "problem"
> > > >
> > > > I didn't say it was a "problem."  Please don't introduce conflict where 
> > > > none exists.
> > > 
> > > If you don't find the special casing of NIL a problem with alists and
> > > plists compared to dlists, it's a little silly to list the absence of a
> > > special case as an advantage of dlists.
> > 
> > I like blue cars.  So if I were to go shopping for a car, a blue car 
> > would have an advantage over a red one.  I would not say, however, that 
> > there is therefore a "problem" with red cars.
> > 
> > Analogously, some people like an object-oriented programming style.  For 
> > such people, DLists offer an advantage over PLists or ALists.  It does 
> > not follow that PLists and ALists have a "problem."
> > 
> > rg
> 
> All you've done is add a level of indirection.

I never meant to imply that DLists were a major breakthrough.  I was 
just asking if they appeared in the literature.  (They do.)

>  It's just as easy to do that with alists and plists.

That's true, but then they aren't ALists and PLists any more, they are 
some other data structure that happens to contain an AList or a PList.  
You couldn't pass one of these directly to ASSOC or GETF.

rg
0
Reply rNOSPAMon (1854) 7/27/2009 3:30:41 PM

On Jul 26, 1:39=A0pm, Ron Garret <rNOSPA...@flownet.com> wrote:

> But all that is neither here nor there, because my actual question is:
> has all this been thought of before? =A0I can't imagine that it hasn't
> been, but I've never seen it in any Lisp text. =A0If there's literature o=
n
> this, can someone point me to a reference? =A0Do these structures have an
> actual name?

No literature pointer for you (other than
source) but I *think* I recall that what
you call a D-list representation is sometimes
used to represent environment frames in SCM and
Guile.

-t
0
Reply lord2845 (83) 7/27/2009 4:14:24 PM

On Jul 27, 11:30=A0am, Ron Garret <rNOSPA...@flownet.com> wrote:

> I never meant to imply that DLists were a major breakthrough. =A0I was
> just asking if they appeared in the literature.

I think it's great!  If you hadn't had that brainstorm, then I'm sure
I would've been forever ignorant of the idea. Because I surely
wouldn't have thought of it.  And I'm pretty sure I would've just read
right past it without noting the import if I ever read SICP or came
across the AIM doc (which I do browse those sometimes, but you know,
"in one ear, out the other").
0
Reply daniel.eliason (172) 7/27/2009 7:14:08 PM

In article 
<0d8f8c2f-c47b-41e3-9141-1934132c23be@l35g2000pra.googlegroups.com>,
 fortunatus <daniel.eliason@excite.com> wrote:

> On Jul 27, 11:30�am, Ron Garret <rNOSPA...@flownet.com> wrote:
> 
> > I never meant to imply that DLists were a major breakthrough. �I was
> > just asking if they appeared in the literature.
> 
> I think it's great!  If you hadn't had that brainstorm, then I'm sure
> I would've been forever ignorant of the idea. Because I surely
> wouldn't have thought of it.  And I'm pretty sure I would've just read
> right past it without noting the import if I ever read SICP or came
> across the AIM doc (which I do browse those sometimes, but you know,
> "in one ear, out the other").

Thanks.  My interest in this is primarily pedagogical, so that's good to 
know.

rg
0
Reply rNOSPAMon (1854) 7/27/2009 9:17:39 PM

In article <rNOSPAMon-C519F5.08304027072009@news.albasani.net>,
 Ron Garret <rNOSPAMon@flownet.com> wrote:

> In article <barmar-68EA64.08444327072009@news.eternal-september.org>,
>  Barry Margolin <barmar@alum.mit.edu> wrote:
> 
> >  It's just as easy to do that with alists and plists.
> 
> That's true, but then they aren't ALists and PLists any more, they are 
> some other data structure that happens to contain an AList or a PList.  
> You couldn't pass one of these directly to ASSOC or GETF.

So?  You can't pass D-lists to any standard functions, either.  Either 
way you have to define new functions, so you could just as easily add 
functions that work with the wrapped plists or alists.

In fact, Maclisp did this with plists.  Originally, plists were only 
available as attributes of symbols, so they served as the indirection.  
Then they expanded it to "disembodied plists" -- if you gave GET a cons, 
it operated on the plist in its CDR (and conversely, CDR of a symbol 
would return its plist -- I assume they simply laid out both objects so 
that the same location was used for both).

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
0
Reply barmar (5623) 7/28/2009 2:27:12 PM

In article <barmar-BA3AE3.10271228072009@news.eternal-september.org>,
 Barry Margolin <barmar@alum.mit.edu> wrote:

> In article <rNOSPAMon-C519F5.08304027072009@news.albasani.net>,
>  Ron Garret <rNOSPAMon@flownet.com> wrote:
> 
> > In article <barmar-68EA64.08444327072009@news.eternal-september.org>,
> >  Barry Margolin <barmar@alum.mit.edu> wrote:
> > 
> > >  It's just as easy to do that with alists and plists.
> > 
> > That's true, but then they aren't ALists and PLists any more, they are 
> > some other data structure that happens to contain an AList or a PList.  
> > You couldn't pass one of these directly to ASSOC or GETF.
> 
> So?  You can't pass D-lists to any standard functions, either.  Either 
> way you have to define new functions, so you could just as easily add 
> functions that work with the wrapped plists or alists.

That's right.  And your point would be...?  (Keep in mind that my 
original question was: does this data structure appear in the 
literature?)

rg
0
Reply rNOSPAMon (1854) 7/28/2009 3:00:50 PM

In article <rNOSPAMon-9A4CD7.08004928072009@news.albasani.net>,
 Ron Garret <rNOSPAMon@flownet.com> wrote:

> In article <barmar-BA3AE3.10271228072009@news.eternal-september.org>,
>  Barry Margolin <barmar@alum.mit.edu> wrote:
> 
> > In article <rNOSPAMon-C519F5.08304027072009@news.albasani.net>,
> >  Ron Garret <rNOSPAMon@flownet.com> wrote:
> > 
> > > In article <barmar-68EA64.08444327072009@news.eternal-september.org>,
> > >  Barry Margolin <barmar@alum.mit.edu> wrote:
> > > 
> > > >  It's just as easy to do that with alists and plists.
> > > 
> > > That's true, but then they aren't ALists and PLists any more, they are 
> > > some other data structure that happens to contain an AList or a PList.  
> > > You couldn't pass one of these directly to ASSOC or GETF.
> > 
> > So?  You can't pass D-lists to any standard functions, either.  Either 
> > way you have to define new functions, so you could just as easily add 
> > functions that work with the wrapped plists or alists.
> 
> That's right.  And your point would be...?  (Keep in mind that my 
> original question was: does this data structure appear in the 
> literature?)

And I would answer that yes, the idea of adding a wrapper around a data 
structure appears in the literature very often.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
0
Reply barmar (5623) 7/28/2009 3:06:50 PM

 ZB> If you don't find the special casing of NIL a problem with alists and
 ZB> plists compared to dlists, it's a little silly to list the absence of a
 ZB> special case as an advantage of dlists.

Dlists are more flexible, as they can be extended both destructively and
non-destructively, while alists and plists can be extended only 
non-destructively.

In some cases this might be an advantage -- e.g. you started using some 
container
in a functional style, but then you need to use it in some place where such 
use is
not possible -- e.g. you need to pass it as function's parameter, for 
example. If you've
chose dlist, it wouldn't be a problem -- you can just use it destructively 
as it is,
while if your choice was alist or plist, you either need to wrap it and 
create some handling
code (some hassle...) or restructute your code to avoid destructive usage. 
So with dlist
you'll have less hassle.

Now, if dlist has advantage, that means alist and plist have disadvantages.

But it is not like alists and plists have problems --ANY design decision is 
a trade-off, it
 has both advantages and disadvantages, that's perfectly normal. 
Disadvantages become
problems only when choice was wrong and design decision cannot satisfy 
requirements.



0
Reply udodenko (1040) 7/28/2009 3:15:39 PM

In article <barmar-68B312.11065028072009@news.eternal-september.org>,
 Barry Margolin <barmar@alum.mit.edu> wrote:

> In article <rNOSPAMon-9A4CD7.08004928072009@news.albasani.net>,
>  Ron Garret <rNOSPAMon@flownet.com> wrote:
> 
> > In article <barmar-BA3AE3.10271228072009@news.eternal-september.org>,
> >  Barry Margolin <barmar@alum.mit.edu> wrote:
> > 
> > > In article <rNOSPAMon-C519F5.08304027072009@news.albasani.net>,
> > >  Ron Garret <rNOSPAMon@flownet.com> wrote:
> > > 
> > > > In article <barmar-68EA64.08444327072009@news.eternal-september.org>,
> > > >  Barry Margolin <barmar@alum.mit.edu> wrote:
> > > > 
> > > > >  It's just as easy to do that with alists and plists.
> > > > 
> > > > That's true, but then they aren't ALists and PLists any more, they are 
> > > > some other data structure that happens to contain an AList or a PList.  
> > > > You couldn't pass one of these directly to ASSOC or GETF.
> > > 
> > > So?  You can't pass D-lists to any standard functions, either.  Either 
> > > way you have to define new functions, so you could just as easily add 
> > > functions that work with the wrapped plists or alists.
> > 
> > That's right.  And your point would be...?  (Keep in mind that my 
> > original question was: does this data structure appear in the 
> > literature?)
> 
> And I would answer that yes, the idea of adding a wrapper around a data 
> structure appears in the literature very often.

Ah.  Well, in response to that I would say that D-Lists are not JUST a 
wrapper.  That they are a wrapper is the reason that they can be used in 
an object-oriented way without having to treat the empty collection 
specially.  But D-Lists also separate the keys from the values which 
neither ALists or PLists do, even when they are wrapped.  (That's the 
reason I called them D-Lists -- because the keys and values are 
Disconnected).  That separation provides additional benefits (which also 
appear in the literature as it turns out).

rg
0
Reply rNOSPAMon (1854) 7/28/2009 4:21:55 PM

In article <4a6f1626$0$300$14726298@news.sunsite.dk>,
 "Alex Mizrahi" <udodenko@users.sourceforge.net> wrote:

>  ZB> If you don't find the special casing of NIL a problem with alists and
>  ZB> plists compared to dlists, it's a little silly to list the absence of a
>  ZB> special case as an advantage of dlists.
> 
> Dlists are more flexible, as they can be extended both destructively and
> non-destructively, while alists and plists can be extended only 
> non-destructively.

That's not true.  Both ALists and PLists can be extended destructively, 
except in the case where they contain no bindings, which has to be 
handled as a special case.

rg
0
Reply rNOSPAMon (1854) 7/28/2009 4:24:14 PM

On Jul 26, 7:39=A0pm, Ron Garret <rNOSPA...@flownet.com> wrote:

> while P-Lists are structured like so:
>
> (key value key value ...)

Unless they're disembodied plists, in which case they're structured
like so:

 (nil key value key value ...)

These aren't CL-style plists, but they are historically important, and
still exist as a fundemental data structure in at least one
contemporary dialect (Skill).

> There is a third representation of an abstract associative map, which
> I've never seen mentioned before. =A0But it is so obvious I can't believe
> that the idea is original with me. =A0For the moment I've dubbed them
> DLists. =A0They look like this:
>
> ((key1 key2 ... keyN) value1 value2 ... valueN)
>
> DLists are just as efficient as ALists and PLists for all common
> operations, but they have several advantages over either ALists or
> PLists:
>
> 1. =A0The empty DList is not (), it's (()). =A0This means that you can pu=
sh
> new bindings onto a DList without having to special-case NIL like you do
> with ALists or Plists.

True enough for CL-style plists, but disembodied plists have this
attribute, too. Another bit you didn't mention that they both share is
object identity for the "dictionary". A related property is that dpls
give you a way to identify the meaning of the structure, by putting
something descriptive (the "class name" of the plist if you will) in
the car.

> 2. =A0When using a DList as a model of a lexical environment, the keys an=
d
> values are cleanly separated, so you can compile a lexical access simply
> by looking up the position of the key in the CAR of the DList, after
> which you can discard the CAR of the DList with no loss of
> functionality. =A0In other words, (deref dlist key) is equivalent to (nth
> (position key (car dlist)) (cdr dlist)), and (position key (car dlist))
> is a compile-time constant.

True as far as it goes, although you'd really want to compile those
references into indexes into a vector, not a list. You could make it
work with dlists, but I think it would be about as much work as using
alists.

> 3. =A0It is trivial to replace the CAR and the CDR of a DList with vector=
s
> (optionally adjustable vectors with fill pointers, though for the common
> use case of modeling lambda bindings this would not be necessary), in
> which case dereferencing constant keys can be done in amortized O(1)
> time. =A0This transformation is not possible with ALists or PLists. =A0Of
> course, it is possible to dereference constant keys for ALists and
> PLists in amortized O(1) time by keeping a reference to the value cell
> itself, but separating the steps so that there is a tangible
> intermediate result that is an integer offset into a value vector I
> believe has pedagogical value when teaching students how closures are
> compiled.

This is a nice property (although it doesn't really easily apply to
environments produced by compilers, since you want shared tails for
them).

> 4. =A0Multiple D-Lists can share the same key list, making D-Lists more
> space efficient (by a factor asymptotically approaching 2) for the
> common use case of modeling lexical environments that get instantiated
> multiple times.
>
> But all that is neither here nor there, because my actual question is:
> has all this been thought of before? =A0I can't imagine that it hasn't
> been, but I've never seen it in any Lisp text. =A0If there's literature o=
n
> this, can someone point me to a reference? =A0Do these structures have an
> actual name?

You mention down-thread that they are mentioned elsewhere. I may have
totally spaced, but did you mention where?
0
Reply tburdick (336) 7/28/2009 8:06:48 PM

In article 
<38434cfe-78cd-4115-b244-1719ebf19ba3@o6g2000yqj.googlegroups.com>,
 "Thomas F. Burdick" <tburdick@gmail.com> wrote:

> > 2. �When using a DList as a model of a lexical environment, the keys and
> > values are cleanly separated, so you can compile a lexical access simply
> > by looking up the position of the key in the CAR of the DList, after
> > which you can discard the CAR of the DList with no loss of
> > functionality. �In other words, (deref dlist key) is equivalent to (nth
> > (position key (car dlist)) (cdr dlist)), and (position key (car dlist))
> > is a compile-time constant.
> 
> True as far as it goes, although you'd really want to compile those
> references into indexes into a vector, not a list. You could make it
> work with dlists, but I think it would be about as much work as using
> alists.

Not at all.  This is one the things that I think is cool about DLists.  
Transitioning from ((key ...) value ...), which is to say ((key ...) . 
(value ...)) to ((key ...) . #(value ...)) is trivial.

> > 3. �It is trivial to replace the CAR and the CDR of a DList with vectors
> > (optionally adjustable vectors with fill pointers, though for the common
> > use case of modeling lambda bindings this would not be necessary), in
> > which case dereferencing constant keys can be done in amortized O(1)
> > time. �This transformation is not possible with ALists or PLists. �Of
> > course, it is possible to dereference constant keys for ALists and
> > PLists in amortized O(1) time by keeping a reference to the value cell
> > itself, but separating the steps so that there is a tangible
> > intermediate result that is an integer offset into a value vector I
> > believe has pedagogical value when teaching students how closures are
> > compiled.
> 
> This is a nice property (although it doesn't really easily apply to
> environments produced by compilers, since you want shared tails for
> them).

You can have shared tails with DLists, though not if you do the 
list-to-vector transformation above.  In that case what I do is chain 
DLists together, so that an individual DList is a single frame in the 
call chain.  This is really what you want for closures anyway.

> > 4. �Multiple D-Lists can share the same key list, making D-Lists more
> > space efficient (by a factor asymptotically approaching 2) for the
> > common use case of modeling lexical environments that get instantiated
> > multiple times.
> >
> > But all that is neither here nor there, because my actual question is:
> > has all this been thought of before? �I can't imagine that it hasn't
> > been, but I've never seen it in any Lisp text. �If there's literature on
> > this, can someone point me to a reference? �Do these structures have an
> > actual name?
> 
> You mention down-thread that they are mentioned elsewhere. I may have
> totally spaced, but did you mention where?

Not me, it was Rob Warnock and Mattias Nilsson.

rg
0
Reply rNOSPAMon (1854) 7/28/2009 8:51:19 PM

On Jul 28, 10:51=A0pm, Ron Garret <rNOSPA...@flownet.com> wrote:
> In article
> <38434cfe-78cd-4115-b244-1719ebf19...@o6g2000yqj.googlegroups.com>,
> =A0"Thomas F. Burdick" <tburd...@gmail.com> wrote:
>
> > > 2. =A0When using a DList as a model of a lexical environment, the key=
s and
> > > values are cleanly separated, so you can compile a lexical access sim=
ply
> > > by looking up the position of the key in the CAR of the DList, after
> > > which you can discard the CAR of the DList with no loss of
> > > functionality. =A0In other words, (deref dlist key) is equivalent to =
(nth
> > > (position key (car dlist)) (cdr dlist)), and (position key (car dlist=
))
> > > is a compile-time constant.
>
> > True as far as it goes, although you'd really want to compile those
> > references into indexes into a vector, not a list. You could make it
> > work with dlists, but I think it would be about as much work as using
> > alists.
>
> Not at all. =A0This is one the things that I think is cool about DLists. =
=A0
> Transitioning from ((key ...) value ...), which is to say ((key ...) .
> (value ...)) to ((key ...) . #(value ...)) is trivial.

Sure, no doubt. What I meant was, if you have a situation like this:

  (let (a)
    (list (lambda (b) (setq a b) a)
          (lambda (b) (prog1 a (setq a b)))))

And you have your environments like so:

  ((b . #1=3D(a)) . (nil . #2=3D(nil)))
  ((b . #1#) . (nil . #2#))

Which would be the easy way to do things in a simple compiler, there's
no simple way to turn the binding parts of those environments into
vectors. You have to do the same work as with alists if you have
multiple frames with shared tails.

> > > 3. =A0It is trivial to replace the CAR and the CDR of a DList with ve=
ctors
> > > (optionally adjustable vectors with fill pointers, though for the com=
mon
> > > use case of modeling lambda bindings this would not be necessary), in
> > > which case dereferencing constant keys can be done in amortized O(1)
> > > time. =A0This transformation is not possible with ALists or PLists. =
=A0Of
> > > course, it is possible to dereference constant keys for ALists and
> > > PLists in amortized O(1) time by keeping a reference to the value cel=
l
> > > itself, but separating the steps so that there is a tangible
> > > intermediate result that is an integer offset into a value vector I
> > > believe has pedagogical value when teaching students how closures are
> > > compiled.
>
> > This is a nice property (although it doesn't really easily apply to
> > environments produced by compilers, since you want shared tails for
> > them).
>
> You can have shared tails with DLists, though not if you do the
> list-to-vector transformation above. =A0In that case what I do is chain
> DLists together, so that an individual DList is a single frame in the
> call chain. =A0This is really what you want for closures anyway.

Right, I think we're saying the same thing. You get shared tails or
you get easy transformation into vectors. Whereas for compiling
closures you want both.

> > > 4. =A0Multiple D-Lists can share the same key list, making D-Lists mo=
re
> > > space efficient (by a factor asymptotically approaching 2) for the
> > > common use case of modeling lexical environments that get instantiate=
d
> > > multiple times.
>
> > > But all that is neither here nor there, because my actual question is=
:
> > > has all this been thought of before? =A0I can't imagine that it hasn'=
t
> > > been, but I've never seen it in any Lisp text. =A0If there's literatu=
re on
> > > this, can someone point me to a reference? =A0Do these structures hav=
e an
> > > actual name?
>
> > You mention down-thread that they are mentioned elsewhere. I may have
> > totally spaced, but did you mention where?
>
> Not me, it was Rob Warnock and Mattias Nilsson.

Ah thanks, I somehow missed that bit of the thread (I blame Google
Groups).
0
Reply tburdick (336) 7/29/2009 8:17:17 AM

By the way, another useful property of d-lists to represent
environments: if you're defining a dynamically scoped dialect, binding
your variables in the host lisp gets super-easy:

  (progv (car env) (cdr env)
    ...)
0
Reply tburdick (336) 7/29/2009 8:23:35 AM

On Jul 27, 8:23 am, Ron Garret <rNOSPA...@flownet.com> wrote:

[[...]]

> If we want to treat associative maps as objects with state independent
> of the places where they are stored, we can do e.g. this with DLists:
>
> (defun add-binding-to-dlist (key value dlist)
>   (push key (car dlist))
>   (push value (cdr dlist))
>   dlist)
>
> which works thusly:
>
> ? (setf dlist (list nil))  ; Empty DList
> (NIL)
> ? (add-binding-to-dlist 'k1 'v1 dlist)
> ((K1) V1)
> ? dlist
> ((K1) V1)
> ?
>
> If we try to do the analogous thing with ALists or PLists it's not quite
> possible.  We can do e.g. this:
>
> (defun add-binding-to-alist (key value alist)
>   (let ((temp (car alist)))
>     (rplaca alist (cons key value))
>     (rplacd alist (cons temp (cdr alist)))
>     alist))
>
> which works as long as the list isn't empty:

[[...]]

> In other words, all DLists are of type PAIR, even the empty DList.  All
> ALists and PLists are of type PAIR *except* the empty AList/PList, which
> is of type NULL.
>
> rg

Actually it's not so bad with plists. By adopting the appropriate
programming style, I've typically found that you don't have to special
case nil if you do

(setf (getf my-plist key) value)

instead. This is very concise and handles the case where my-plist is
nil, just fine.

(let ((my-plist (list)))
 (setf (getf my-plist :name) "Pete")
 my-plist)
==> (:NAME "Pete")

Of course, you still have a problem with the identity of your
'object'. You cannot abstract this away with a function. Eg the
analogous counterpart to your alist example is:

(defun add-binding-to-plist (key value plist)
 (setf (getf plist key) value)
 plist)
==> add-binding-to-plist

(let ((x (list)))
 (add-binding-to-plist :name "Pete" x))
==> (:NAME "Pete")

(let ((x (list)))
 (add-binding-to-plist :name "Pete" x)
 x)
==> NIL

When x is not nil, then it's ok I guess.

(let ((x (list :age 20)))
 (add-binding-to-plist :name "Pete" x))
==> (:NAME "Pete" :AGE 20)

(let ((x (list :age 20)))
 (add-binding-to-plist :name "Pete" x)
 x)
==> (:NAME "Pete" :AGE 20)


The answer is probably to adopt a functional style, and if you really
need an abstraction like add-binding-to-plist or somesuch, make it a
macro instead?
0
Reply senatorZergling (101) 7/29/2009 9:37:42 AM

 ZB>>> If you don't find the special casing of NIL a problem with alists and
 ZB>>> plists compared to dlists, it's a little silly to list the absence of
 ZB>>> a special case as an advantage of dlists.
 ??>>
 ??>> Dlists are more flexible, as they can be extended both destructively
 ??>> and non-destructively, while alists and plists can be extended only
 ??>> non-destructively.

 RG> That's not true.  Both ALists and PLists can be extended destructively,
 RG> except in the case where they contain no bindings, which has to be
 RG> handled as a special case.

I.e. they cannot be extended destructively in general case. 


0
Reply udodenko (1040) 7/29/2009 11:18:44 AM

Thomas F. Burdick <tburdick@gmail.com> wrote:
+---------------
| Ron Garret <rNOSPA...@flownet.com> wrote:
| > This is one the things that I think is cool about DLists.
| > Transitioning from ((key ...) value ...), which is to say ((key ...) .
| > (value ...)) to ((key ...) . #(value ...)) is trivial.
| 
| Sure, no doubt. What I meant was, if you have a situation like this:
| 
|   (let (a)
|     (list (lambda (b) (setq a b) a)
|           (lambda (b) (prog1 a (setq a b)))))
| 
| And you have your environments like so:
| 
|   ((b . #1=(a)) . (nil . #2=(nil)))
|   ((b . #1#) . (nil . #2#))
| 
| Which would be the easy way to do things in a simple compiler, there's
| no simple way to turn the binding parts of those environments into
| vectors. You have to do the same work as with alists if you have
| multiple frames with shared tails.
+---------------

Actually, you *can* readily turn them into vectors, by transforming
the shared lexicals into "box"es [a.k.a. "box conversion"]. That is,
your original code gets rewritten something like this:

    (defstruct box val)

    (let ((%a (make-box :val a))
      (list (lambda (b)
	      (setf (box-val %a) b)
	      (box-val %a))
            (lambda (b)
	      (prog1
		(box-val %a)
		(setf (box-val %a) b)))))

and then because %A is itself never mutated, it can be freely copied
without worrying about sharing, e.g.:

    (let ((%a (make-box :val a)))
      (list (let ((%b %a))
	      (lambda (b)
		(setf (box-val %b) b)
		(box-val %b)))
	    (let ((%c %a))
              (lambda (b)
		(prog1
		  (box-val %c)
		  (setf (box-val %c) b))))))

If this transformation is performed on all closed-over variables
which are both shared and mutated, then the closure environments
for each closure can be single unshared vectors, which can be
accessed in O(1). These are called "flat" environments, are used
in both PLT Scheme and CMU Common Lisp, and are discussed in
several places in Queinnec's "Lisp in Small Pieces".

+---------------
| > > This is a nice property (although it doesn't really easily apply to
| > > environments produced by compilers, since you want shared tails for
| > > them).
| >
| > You can have shared tails with DLists, though not if you do the
| > list-to-vector transformation above. In that case what I do is chain
| > DLists together, so that an individual DList is a single frame in the
| > call chain. This is really what you want for closures anyway.
| 
| Right, I think we're saying the same thing. You get shared tails or
| you get easy transformation into vectors. Whereas for compiling
| closures you want both.
+---------------

And you get both (and more) by adding box conversion to the mix.

+---------------
| > > > If there's literature on this, can someone point me to a reference?
| > > > Do these structures have an actual name?
| >
| > > You mention down-thread that they are mentioned elsewhere.
| > > I may have totally spaced, but did you mention where?
| >
| > Not me, it was Rob Warnock and Mattias Nilsson.
| 
| Ah thanks, I somehow missed that bit of the thread (I blame Google Groups).
+---------------

To save you some chasing, Mattias Nilsson referred to AIM-453, and
I referred to SICP2 [*not* SICP1!] and L.i.S.P. [also mentioned above].


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607

0
Reply rpw3 (2294) 7/29/2009 11:54:10 AM

On Jul 29, 1:54=A0pm, r...@rpw3.org (Rob Warnock) wrote:
> Thomas F. Burdick <tburd...@gmail.com> wrote:
> +---------------
> | Ron Garret <rNOSPA...@flownet.com> wrote:
> | > This is one the things that I think is cool about DLists.
> | > Transitioning from ((key ...) value ...), which is to say ((key ...) =
..
> | > (value ...)) to ((key ...) . #(value ...)) is trivial.
> |
> | Sure, no doubt. What I meant was, if you have a situation like this:
> |
> | =A0 (let (a)
> | =A0 =A0 (list (lambda (b) (setq a b) a)
> | =A0 =A0 =A0 =A0 =A0 (lambda (b) (prog1 a (setq a b)))))
> |
> | And you have your environments like so:
> |
> | =A0 ((b . #1=3D(a)) . (nil . #2=3D(nil)))
> | =A0 ((b . #1#) . (nil . #2#))
> |
> | Which would be the easy way to do things in a simple compiler, there's
> | no simple way to turn the binding parts of those environments into
> | vectors. You have to do the same work as with alists if you have
> | multiple frames with shared tails.
> +---------------
>
> Actually, you *can* readily turn them into vectors, by transforming
> the shared lexicals into "box"es [a.k.a. "box conversion"]. That is,
> your original code gets rewritten something like this:

True. But what I was trying to say was that this data structure
doesn't make this any easier. To properly compile closures, there are
a few things you ant to do, including boxing shared variables and
removing references to unreferenced variables in enclosing
environments. Dlists do hint a little bit more in the right direction,
but ultimately you'll have the same amount of work to do with any of
the three representations.

> =A0 =A0 (defstruct box val)
>
> =A0 =A0 (let ((%a (make-box :val a))
> =A0 =A0 =A0 (list (lambda (b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf (box-val %a) b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (box-val %a))
> =A0 =A0 =A0 =A0 =A0 =A0 (lambda (b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (prog1
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (box-val %a)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf (box-val %a) b)))))
>
> and then because %A is itself never mutated, it can be freely copied
> without worrying about sharing, e.g.:
>
> =A0 =A0 (let ((%a (make-box :val a)))
> =A0 =A0 =A0 (list (let ((%b %a))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (lambda (b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf (box-val %b) b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (box-val %b)))
> =A0 =A0 =A0 =A0 =A0 =A0 (let ((%c %a))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (lambda (b)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (prog1
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (box-val %c)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf (box-val %c) b))))))
>
> If this transformation is performed on all closed-over variables
> which are both shared and mutated, then the closure environments
> for each closure can be single unshared vectors, which can be
> accessed in O(1). These are called "flat" environments, are used
> in both PLT Scheme and CMU Common Lisp, and are discussed in
> several places in Queinnec's "Lisp in Small Pieces".
>
> +---------------
> | > > This is a nice property (although it doesn't really easily apply to
> | > > environments produced by compilers, since you want shared tails for
> | > > them).
> | >
> | > You can have shared tails with DLists, though not if you do the
> | > list-to-vector transformation above. In that case what I do is chain
> | > DLists together, so that an individual DList is a single frame in the
> | > call chain. This is really what you want for closures anyway.
> |
> | Right, I think we're saying the same thing. You get shared tails or
> | you get easy transformation into vectors. Whereas for compiling
> | closures you want both.
> +---------------
>
> And you get both (and more) by adding box conversion to the mix.
>
> +---------------
> | > > > If there's literature on this, can someone point me to a referenc=
e?
> | > > > Do these structures have an actual name?
> | >
> | > > You mention down-thread that they are mentioned elsewhere.
> | > > I may have totally spaced, but did you mention where?
> | >
> | > Not me, it was Rob Warnock and Mattias Nilsson.
> |
> | Ah thanks, I somehow missed that bit of the thread (I blame Google Grou=
ps).
> +---------------
>
> To save you some chasing, Mattias Nilsson referred to AIM-453, and
> I referred to SICP2 [*not* SICP1!] and L.i.S.P. [also mentioned above].
>
> -Rob
>
> -----
> Rob Warnock =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 <r...@rpw3.org>
> 627 26th Avenue =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 <URL:http://rpw3.org/>
> San Mateo, CA 94403 =A0 =A0 =A0 =A0 =A0 =A0 (650)572-2607

0
Reply tburdick (336) 7/29/2009 12:59:01 PM

In article 
<71a54602-d061-4868-8e8d-584cee0ed3b7@d32g2000yqh.googlegroups.com>,
 "Thomas F. Burdick" <tburdick@gmail.com> wrote:

> On Jul 28, 10:51�pm, Ron Garret <rNOSPA...@flownet.com> wrote:
> > In article
> > <38434cfe-78cd-4115-b244-1719ebf19...@o6g2000yqj.googlegroups.com>,
> > �"Thomas F. Burdick" <tburd...@gmail.com> wrote:
> >
> > > > 2. �When using a DList as a model of a lexical environment, the keys and
> > > > values are cleanly separated, so you can compile a lexical access simply
> > > > by looking up the position of the key in the CAR of the DList, after
> > > > which you can discard the CAR of the DList with no loss of
> > > > functionality. �In other words, (deref dlist key) is equivalent to (nth
> > > > (position key (car dlist)) (cdr dlist)), and (position key (car dlist))
> > > > is a compile-time constant.
> >
> > > True as far as it goes, although you'd really want to compile those
> > > references into indexes into a vector, not a list. You could make it
> > > work with dlists, but I think it would be about as much work as using
> > > alists.
> >
> > Not at all. �This is one the things that I think is cool about DLists. �
> > Transitioning from ((key ...) value ...), which is to say ((key ...) .
> > (value ...)) to ((key ...) . #(value ...)) is trivial.
> 
> Sure, no doubt. What I meant was, if you have a situation like this:
> 
>   (let (a)
>     (list (lambda (b) (setq a b) a)
>           (lambda (b) (prog1 a (setq a b)))))
> 
> And you have your environments like so:
> 
>   ((b . #1=(a)) . (nil . #2=(nil)))
>   ((b . #1#) . (nil . #2#))
> 
> Which would be the easy way to do things in a simple compiler, there's
> no simple way to turn the binding parts of those environments into
> vectors. You have to do the same work as with alists if you have
> multiple frames with shared tails.

Ah.  What about this:

#((#(b) . #(...))) (#(a) . #(...)))

In other words, instead of trying to fram all the frames into a single 
D-List, I'd have a vector of D-Lists, one per frame.  That would let you 
share value vectors.  (Not clear if they still ought to be called 
D-Lists if their components are vectors.)

rg
0
Reply rNOSPAMon (1854) 7/30/2009 3:37:32 AM

34 Replies
31 Views

(page loaded in 0.39 seconds)


Reply: