Arc Forumnew | comments | leaders | submitlogin
Dotted lists - HUH! What are they good for?
4 points by nzc 6085 days ago | 17 comments
What practical use do modern day lisp programmers find for dotted pairs?

Would anyone really care if they just went away?

They seem to be an implementation detail more than an essential part of lists, per se.



5 points by sjs 6085 days ago | link

Considering that (1 2 3) is just sugar for (1 . (2 . (3 . nil))) modern lisp programmers find many practical uses for dotted lists.

In this case the implementation and interface are so intertwined that it seems difficult (impossible?) to change one without significantly changing the other. As absz pointed out, car, cdr, cons would have to be rethought and redesigned or simply replaced.

If you get rid of cons/car/cdr I don't think you really have lisp anymore. That's not to say non-lisps are dumb or useless, but when you set out to create a better lisp you should at least create a lisp.

I think that a sequence abstraction, à la Clojure[1,2], is a nice idea though.

  [1] http://clojure.sourceforge.net/
  [2] http://clojure.blip.tv/file/707974/

-----

6 points by kennytilton 6085 days ago | link

"Would anyone really care if they just went away?"

You mean a cons cell only has a CAR slot, there is no CDR? :)

Or that you would ban me from storing anything other than nil or another cons in the cdr?

ie, dotted lists are not really "there", so they cannot go away.

-----

2 points by nzc 6085 days ago | link

Neh, what I meant was, you can have a thing that quacks like a list and never see the need for a dotted pair.

That can be hidden below the abstraction. See, case in point, lists/arrays in Ruby, which are more or less lists without the car and cdr part. Although, you do get a 'nil' if you access beyond the end of the array. ;-)

-----

9 points by kennytilton 6085 days ago | link

Ruby lists can quack? Bah, let me know when they can mate, that's when you know you have the same species: ie, can two Ruby more-or-less lists have shared structure, formed say by ruby-consing a different element onto the same list?

And ducks can nest. How about Ruby lists? I have always thought the language should have been called Trep, for Tree Processing language. Can I build a Ruby tree and then quickly flatten by juggling some Ruby ducktails?

As for "That can be hidden below the abstraction", OK, now you have a duck: moving smoothly on the surface and paddling like crazy beneath.

The whole comparison just seems (sorry on more levels than one) daffy.

-----

3 points by absz 6085 days ago | link

Indeed, you are correct. Ruby[1] doesn't have "native" lists, it has native arrays. Observe:

  irb(main):001:0> [].class
  => Array
There is no Ruby cons, nor Ruby car, nor Ruby cdr. There is y.unshift x or [x] + y for cons (though these cannot constructed "dotted Arrays"), arr[0] or arr.first for car, and arr[1..-1] for cdr, but they denote no structure-sharing. However, flattening would merely be arr.flatten—of course it doesn't work by cdr-juggling, but that's because there are no cdrs.

I'm not really sure what the grandparent post means: "lists without the car and cdr part"? That sounds to me like a very good definition of an... array![2]

Also, that set of duck puns/references was fantastic. Well done.

[1]: Which is a very nice language.

[2]: Well, without the O(1) access time, but I digress.

-----

5 points by kennytilton 6084 days ago | link

"that set of duck puns/references was fantastic."

I can take no credit -- they just popped out of my keyboard. There must be some poorly understood connection between algorithms, data structures, and waterfowl.

-----

3 points by absz 6084 days ago | link

I smell a Ph.D. thesis afoot... awing?

Actually, they (the infamous "they") did a study, and apparently, ducks are the funniest animal. Take that with as large a grain of salt as you think is appropriate :)

-----

1 point by vincenz 6069 days ago | link

This is directly related to the existence of "daffy duck"

-----

4 points by sacado 6085 days ago | link

I use them to build trees, two-sided lists, when I need to encapsulate a value (e.g. to dinsinguish between nil-the-boolean and nil-the-empty-list). For all those things, opaque lists or hashes could be used, too.

But the main use of dotted lists is for recursively-built and recursively-explored lists :

  (def foo (a b)
    (if a 
      (cons (car b) (foo (cdr b))
      nil)
and relatives appear in so much of my code... I don't think I would like to see dotted pairs go away. And if you don't like them, you can always use (list ...), (l 0), (l 1), (last l), rev, ... and not care about actual implementation.

-----

3 points by nzc 6085 days ago | link

I know, I know, I just asked this question b/c I saw someone else's post about dotted pair containing lists (old timers would say "s-expressions") not working properly in some cases in arc, and I having noodled around implementing lisp in ruby recently, and having stubbed my toe on implementing cons after having chosen arrays as the underlying implementation of lists, I thought I'd throw this out there and see what people had to say.

-----

3 points by absz 6085 days ago | link

One use of dotted lists is the degenerate case of a dotted pair: (cons 'a 'b). Slightly nicer for representing a pair than a complete list (though less so with the lst.n syntax). But it seems to me like they're important to have because of what a list is. A list has a car and a cdr: (car (cons x y)) -> x, and (cdr (cons x y)) -> y. If you remove dotted lists, you break that valuable identity. Would (cons 'x 'y) be an error, or implicitly create the list '(x y)? Either way, there's inconsistency that will come back to bite you.

-----

9 points by pg 6085 days ago | link

They make a good axiom because they're so minimal.

-----

2 points by nzc 6085 days ago | link

I see that; it just seems like they don't have a huge amount of practical utility. I mean, they're nice to have, but when I was programming in CL, one rarely if ever saw them in production code.

But I think you're right -- they have that "feeling the bits between your toes" character.

They're not necessary in order to have a list abstraction, but they are the minimal thing you could build lists out of.

-----

8 points by pg 6085 days ago | link

The whole point of the axiomatic approach is that you don't program in the axioms themselves. But you still do want to have the things you do program in built out of the smallest set of axioms.

-----

2 points by map 6085 days ago | link

from the newLISP manual

Evaluation of (cons x '()) yields (x), but (cons x nil) yields (x nil) because nil is treated as a boolean value when evaluated instead of as an empty list. The cons of two atoms in newLISP does not yield a dotted pair, but rather a two-element list. The predicate atom? is true for nil, but false for the empty list. The empty list in newLISP is only an empty list and not equal to nil.

A list in newLISP is a LISP cell of type list. It acts like a container for the linked list of elements making up the list cell's contents. There is no dotted pair in newLISP because the cdr (tail) part of a LISP cell always points to another LISP cell and never to a basic data type, such as a number or a symbol. Only the car (head) part may contain a basic data type.

-----

2 points by Jesin 6075 days ago | link

This is why Arc is better than newLISP. The only reason I can think of for this is that newLISP is trying to protect newbies from the actual structure of lists by telling them that cons adds an element to the beginning of a list, car gets the first element of a list, and cdr gets the rest of the list.

Arc doesn't try to protect people from these kinds of things. It's not like we can't handle the real meaning of cons.

-----

2 points by almkglor 6085 days ago | link

Here's an implementation of lists which work mostly as arrays, until you actually use scdr. This seamlessly handles dotted lists and is optimized for proper lists.

http://www.arclanguage.com/item?id=4146

Edit: arrays are unrolled lists where m=inf, while standard Lisp cons cells are unrolled lists where m=1.

Edit 2: remember, (isnt implementation interface)

-----