5

[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?

  • 1
    Great question. It is confusing for us noobs. – RichieHH Feb 12 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 at 5:14
4

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.

| improve this answer | |
  • 4
    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 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 at 15:57
  • 1
    I guess this is R. Chassell means by "When a variable is set to a list with setq, it stores the address of the first box in the variable". To sum up, (setq x '(1 2 3 4)), does not really fill the "value cell" of x with the values from the list. Instead, x becomes a pointer towards the "first box" of the list I have supplied (whose values are stored at given places in the memory). And then, y also becomes a pointer towards the same places. So, x and y are both pointers and point towards the same object, that's why (eq x y) returns t. Well, this is a little brainfuck. :) – Philopolis Feb 12 at 15:58
  • 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 at 16:28
  • 1
    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 at 17:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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