6

[Warning : these are noob questions.]

I'm a beginner in Emacs Lisp and I would like to be sure that I understand well what I'm really doing when I set a value to a variable with setq or let.

Here is a piece of code:

(setq x '(1 2 3 4))     ; define x
(setq y x)              ; define y
(setcar y 9)            ; modify CAR of y
y                       ; -> (9 2 3 4): y has changed (ok)
x                       ; -> (9 2 3 4): but x has changed too!
  1. It seems that when you define a symbol and give it the value of another symbol, this basically means that the two symbols become the same object?

    (eq x y)             ; -> t
    

    (I expected that the instruction (setq y x) would make an "independant copy" of x, as it would be the case if you do y <- x in R language for example. Or, more formally, I thought this instruction would only fill the "value cell" of y by evaluating (symbol-value 'x), but without "binding" those two objects together.)

  2. This is really a matter of pointers, if I understand well. (setq y x)creates a new symbol which is basically bound to the same address as x? (I.e., y points towards x which points towards a given value, and so if you modify y, you will also modify x because both of them point towards the same address "by transitivity"?)

  3. Robert Chassell's book says that "when a Lisp variable is set to a value, it is provided with the address of the list to which the variable refers", but I cannot figure out what this means formally (where is this address stored?). A Lisp symbol is made of 4 components (name, value, function, properties). So, when I do (setq y x), the "value cell" of y is really an address / a pointer towards x?

2
  • 1
    Great question. It is confusing for us noobs.
    – RichieHH
    Feb 12, 2020 at 12:23
  • 1
    This is the same behavior as seen in Python (and other dynamic languages). There is an extra step in going from a variable to the value. Variables don't have the address of values, they have the address of a spot in memory that holds the address of the value. So x = y doesn't copy the value, it copies the address of the spot in memory which holds the address of the value. Don't know about EmacsLisp, but Python has a way of duplicating the value so x and y can't refer to seoarate lists.
    – Scooter
    Sep 22, 2020 at 5:14

1 Answer 1

5

setq is doing like expected, the thing here is, that (1 2 3 4) is not a value, so it is not what you think it is.

  • a Place is a location in memory.

  • x and y are Symbols.

  • a Symbol merely points to a place. So x points to (the first cons of) your list.

  • (1 2 3 4) is a List of conses (aka a "chain" of conses).

  • (1 2 3 4) is not a value, but multiple chained values.
  • a list is constructed like this (cons 1 (cons 2 (cons 3 nil))).
  • a cons consists of two pointers (car . cdr) to the places where the values are stored.
  • a cons by itself is stored at a place. (I'm not perfectly sure with that one)

What did you do?:

  • your new y points, after setq to the same place like x, because you said: point to the list referenced by symbol x.
  • You changed the content of your list, which exists only once in memory.

I hope I got that right. :)

Good question, btw.

5
  • 6
    Most of what you say is right, IMO. But (1 2 3 4) is a value. It's a list of 4 elements. Don't confuse Lisp values with their implementation or manipulation. Same thing for a string, for example: "1 2 3 4" is a single (string) value. But you can access any elements of the string. Yes, element access is different in the cases of a string, which is an array/vector, and a list. But they are both Lisp values.
    – Drew
    Feb 12, 2020 at 15:39
  • 1
    This is really helpful, thanks! So I think it's even worse than I expected: I also misunderstood what is really a list! Because the behavior is different if we execute the three instructions (setq x "a"), (setq y x) and (setq y "b"): this time, x remains unchanged after those three instructions. If I understand well, this is simply because (unlike with those simple character values) lists involve pointers.
    – Philopolis
    Feb 12, 2020 at 15:57
  • 1
    Yes, it is confusing. No two ways about it. Did you try with strings? Why are they not "addresses" then?... Is a string a list of chars... I shall get my cape... ;)
    – RichieHH
    Feb 12, 2020 at 16:28
  • @Drew what I ment to say: (1 2 3 4) is not a single value, but multiple values. Thats different to arrays. Would you agree with that?
    – jue
    Feb 13, 2020 at 9:40
  • 2
    No, it's a single value. The value is a list. A list is implemented as either the atom nil or a cons cell whose cdr is a list. Think string or vector - similar concepts apply: [1 2 3] is a single value, a vector. The vector has 3 elements, which are integer values.
    – Drew
    Feb 13, 2020 at 17:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.