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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Philopolis
  • 1,094
  • 8
  • 14
  • 1
    Great question. It is confusing for us noobs. – RichieHH Feb 12 '20 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 '20 at 05:14

1 Answers1

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.

Drew
  • 75,699
  • 9
  • 109
  • 225
jue
  • 4,476
  • 8
  • 20
  • 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 '20 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 '20 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 '20 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 '20 at 09: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 '20 at 17:48