Comment by lvh
8 years ago
> 4. Their meaning is precise: car just takes the first element of a list. Whereas something called first might reasonably be expected to also give you the first element of a vector, or a string.
That may be true in LISP, but it's not true in Clojure (which I assume is a fair paragon for the first/rest camp), where first works just fine on strings and vectors:
=> (first "abc")
\a
=> (first [1 2 3])
1
> 5. When you're operating on lists as trees, the names first and rest are actively misleading. The car and cdr are the left and right subtrees, not the first and rest of something.
Firstly, trees can clearly branch out more than n=2. Then, nth becomes a much cleaner term than "left" and "right" which immediately limit you to 2 cases. But, let's say we're talking about n=2 trees. Consider:
headmarc.core=> (second [1 2 3])
2
And, of course, if that still seems unreasonable:
(def left first)
(def right second)
... but maybe what you really want is a zipper, which has everything you're asking for and more: https://clojure.github.io/clojure/clojure.zip-api.html#cloju...
TXR Lisp, a dialect with true conses:
I'm not sure if that's what you meant, but the point I was addressing was that "first" is bad because you could reasonably expect it to work on anything sequentialish not just on conses (agreed), and car/cdr is explicitly about conses (agreed). But first, in some Lisps, works just fine on everything sequentialish, including vectors and strings, so I don't consider that a particularly strong argument.
cl, cr I could live with, maybe. (consleft, consright). Other suggestions, head and tail, fst and snd, which have some of the other touted advantages. (I don't necessarily agree with them, but they also don't hurt, so...)
car and cdr is not necessarily about conses. I made them the basis for iterating over any list-like sequences in TXR Lisp. To participate in the protocol, an object can implement methods called cdr, car and nullify. This latter nullify should return nil if the object considers itself as representing "empty". Otherwise it can return the object itself, or possibly something else, like an ordinary list.