reddit / emacs

When to use cons cells explicitly?

EmilySeville7cfg · 2022-07-29 07:00
I don't understand why to write `(a . b)` instead of `(a b)`. When such notation is useful?
7890yuiop · 2022-07-29 07:15
`(a . b)` and `(a b)` are *not* the same. `(a b)` is equivalent to `(a . (b . nil))`. You would rarely ever want to write a proper list like `(a b)` in dotted-pair notation, but there are all kinds of uses for dealing with individual cons cells (alists being an example) where, if the values are constant, dotted-pair notation is convenient. (If the values are not constant, then you would more likely want to call `cons` instead).
Phil-Hudson · 2022-07-29 09:54
Couple of good tutorials: https://cs.gmu.edu/~sean/lisp/cons/ https://riptutorial.com/common-lisp/example/17740/sketching-cons-cells
Phil-Hudson · 2022-07-29 09:56
> (a b) is equivalent to (a . (b . nil)) ... is equivalent to `(a . (b))`
Phil-Hudson · 2022-07-29 10:01
One advantage of a dotted pair `(a . b)` is that it uses less memory than a proper list `(a b)`, as the tutorials I posted will make clear. There are other considerations and trade-offs that might make one or the other the better choice in different contexts. When in doubt, use a list, would be my advice.
J-ky · 2022-07-29 10:46
(a . b) is a simplified version of (cons a b). A pair is different from a list.
deaddyfreddy · 2022-07-29 12:22
The fun thing is Lisp (I mean "classic" dialects here), being a high level language, still force programmers to think about low level implementation details. The funnier thing is car/cdr is a low level thing for an ancient IBM 704 machine from 1954!
SlowValue · 2022-07-30 19:35
> Lisp (I mean "classic" dialects here), being a high level language, still force programmers to think about low level implementation details. The funnier thing is car/cdr is a low level thing for an ancient Could you please elaborate! Assumption: Elisp and Common Lisp are such "classic" dialects you are referring to. Following is, what came into my mind, after I read your comment: `car` and `cdr` are just legacy names for `first` and `rest`. They operate on a built-in datatype, named "cons". Which is used to construct another built-in datatype, a "single linked list". A single element of such a list (a "cons") consist of a data part (aka "first" or "car") and a linking part (aka "rest" or "cdr"). If the "rest" part is `nil`, this marks the end of such an list. So everything (but the names "car" and "cdr", which you don't have to use) is purely functionally aligned to that "single list" datatype. I can't see the "low level thing" you are referring to!
deaddyfreddy · 2022-08-01 11:42
> car and cdr are just legacy names for first and rest. They operate on a built-in datatype, named "cons". Which is used to construct another built-in datatype, a "single linked list". A single element of such a list (a "cons") consist of a data part (aka "first" or "car") and a linking part (aka "rest" or "cdr"). If the "rest" part is nil, this marks the end of such an list. the fun thing is you've just described the low level implementation details of a list https://en.wikipedia.org/wiki/CAR_and_CDR
SlowValue · 2022-08-01 13:06
> you've just described the low level implementation details of a list I've described a **singly** linked list. The organization of a **double** linked list, would look different. A cons and a **singly** linked list are **very basic built in data types**. Other languages like C don't even have them built in. IMO a low level implementation description of a singly linked list, would show what data type a link is, where in relation those two values (car and cdr) are stored (in order to access them) and how access of the next list element is done. Nothing of this was described, because functions `car` and `cdr` are abstractions. *How should a high level description of a **singly** linked list look like, without loosing access to important data?* A Low level implementation detail of cons and car could look like this (examples taken from SICP chapter 2): (define (cons x y) (define (dispatch m) (cond ((= m 0) x) ((= m 1) y) (else (error "Argument not 0 or 1: CONS" m)))) dispatch) (define (car z) (z 0)) or, like that: (define (cons x y) (lambda (m) (m x y))) (define (car z) (z (lambda (p q) p)))
deaddyfreddy · 2022-08-01 14:30
> How should a high level description of a singly linked list look like, without loosing access to important data? IMO high level means "I don't give a shit about details, just give me what I need", the ability to describe business logic in its own terms, not the computer architecture ones.
SlowValue · 2022-08-02 09:03
> ability to describe business logic in its own terms, not the computer architecture ones `car` and `cdr` are just names (out of legacy), they don't describe the implementation anymore.
deaddyfreddy · 2022-08-02 13:30
so no need to use them, `first` and `rest` are much more understandable abstractions. Destructuring is even more readable.
7890yuiop · 2022-08-10 01:57
> (a . b) is a simplified version of (cons a b) Strictly speaking, that's not entirely accurate. `(a . b)` is a *read*-time construct (the lisp reader^1 generates a cons cell), whereas `(cons a b)` is a lisp function call that returns a cons cell when it is *evaluated*. They both ultimately result in a cons cell, but they're not equivalent code. ---- ^1 E.g.: (message . ("%s; %s" . ("you can write your code in dotted pair notation if you really want to" . ("it's all the same to the lisp reader..."))))