2

I was stumbling through the Arc tutorial when I got sort of confused with this:

Quoted from the Arc Tutorial:

Like Common Lisp assignment, Arc's = is not just for variables, but can reach inside structures. So you can use it to modify lists:

arc> x
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)

But lisp is executed recursively, right? It says that car returns the first value in a list. So:

arc> (car x)
a

which makes sense, but then why isn't (= (car x) 'z) equal to (= a 'z), which would result in:

arc> a
z
arc> x
(a b) ; Note how this hasn't changed

but it doesn't. Instead, it appears that (= (car x) 'z) seems to have the effects of (= x (list 'z (car (cdr x)))):

arc> (= x '(a b))
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)


...


arc> (= x '(a b))
(a b)
arc> (= x (list 'z (car (cdr x))))
(z b)
arc> x
(z b)

So why exactly does (= (car x) 'z) work that way and what is it that I'm missing here?


Note: this is my first introduction to LISP.

haneefmubarak
  • 1,911
  • 1
  • 21
  • 32
  • 1
    "Note: this is my first introduction to LISP." Out of curiosity, is this your first introduction to programming? If you have experience with other languages, you might consider something like `a[1] = 2` in a language like C or Java, which *assigns* 2 to the second element of the array. Before storing `2` there, it must have some value, e.g., `7`, but this doesn't somehow assign `2` to `7`. Assignment is usually special in that it has to have a way to refer to a "place" or "location". – Joshua Taylor Dec 31 '14 at 02:45
  • Your understanding of lists seems to be good, but your assumption that everything gets evaluated recursively is wrong. Functions' arguments get evaluated recursively, but `=` is a macro and macros' arguments don't get evaluated, instead, they get their arguments raw as lists or symbols or primitive types. Macros can then internally manually evaluate any arguments, but not necessarily. – enrey Jan 13 '15 at 17:06

4 Answers4

4

= is a special operator, it's not a function. So its arguments are not evaluated according to the normal recursive process. The first argument is treated specially, it identifies a place to assign to, not the value already in that place. It may have to evaluate subexpressions within it to find the place, but once it gets to the place, it stops evaluating. The second argument will be evaluated normally, to get the value to assign there.

Barmar
  • 741,623
  • 53
  • 500
  • 612
2

= appears to be an assignment operator in Arc, the equivalent in Common Lisp would be setf. In this case, (car x) returns the place that is to be modified:

? (defparameter x '(a b))
X
? x
(A B)
? (setf (car x) 'z)
Z
? x
(Z B)

See also here.

uselpa
  • 18,732
  • 2
  • 34
  • 52
  • 3
    [Arc documentation on assignment and places](http://arclanguage.github.io/ref/assignment.html) – Sylwester Dec 30 '14 at 16:38
  • 6
    "(car x) returns the place" **returns** probably isn't the right word here. The important thing is that **(car x)** denotes a place where a value can be stored. – Joshua Taylor Dec 31 '14 at 02:46
2

= is a macro or rather "special operator", which is just a fancy name for built-in macro. Macros' arguments (unlike functions' arguments) aren't evaluated at all, so the = operator gets (car x) unevaluated ==> it get's the list (car x) itself! Now, that = operator contains miniature code walker that traverses the list (car x) and figures out what place would be read from if the list was evaluated. And assigns to that place.

What does it assign? The result of evaluating the second argument, it evaluates that one manually.

So the effective evaluation scheme for = is in fact

(= <unevaluated-argument> <evaluated-argument>)

EDIT: Another example of macro or special operator is if. in (if <cond> <a> <b>), if starts being evaluated first and gets arguments <cond>, <a> and <b> raw - unevaluated. Then it manually evaluates <cond> and depending on the result, it either evaluates <a> or <b> and returns result of that. If everything was really evaluated recursively, you could never have working if or cond or loop or short-circuit and and or and so on...

NOTE: = is probably (= I suppose) a macro and not special operator, at least its equivalent setf in common lisp is a macro. I doubt that P. Graham embedded = directly into the compiler. But it's not really important to know.

enrey
  • 1,621
  • 1
  • 15
  • 29
-1

If you have the book "ANSI Common Lisp", there is such sentence in chapter 3.3 Why Lisp Has No Pointers:

One of Secrets to understanding Lisp is to realize that variables have values in the same way that lists have elements. As conses have pointers to their elements, variables have pointers to their values.

If x is assigned a list:

arc> (= x '(a b))
(a b)

It formulates as such, the variable x points to a list. The 1st position of the list points to the symbol a and the 2nd points to the symbol b:

A variable x points to a list, the 1st position points to symbol a and the 2nd position to symbol b

When car of x is assigned with 'z in (= (car x) 'z), simply the 1st position points the new symbol z.

enter image description here

Finally, in the expression (= a 'z), a variable a is assigned and thus points to the symbol z

enter image description here

jeffruan
  • 294
  • 1
  • 5
  • So if the first position points to `z`, why does `z` automatically point to `b`? – haneefmubarak Jan 02 '15 at 17:28
  • List is constructed by the cons operator under the surface. cons operator creates a pair. The list '(z b) is constructed by (cons 'z (cons 'b nil)), so there are two pairs. The first pair points to both 'z and the next pair. The next pair points to 'b and a nil element which is the end of the list. When we say the first element in the list is 'z, we are actually saying the first element of the first pair in the list is 'z. You could read any lisp introduction book for these. – jeffruan Jan 03 '15 at 02:36
  • 1
    Downvoted, this answer is misleading. Lot of interesting info about lists, but doesn't explain why it assigns to (car x). The final sentence saying that "variable `a` is assigned and thus points to the symbol z" is just straight out wrong, as there's no variable `a` here. `a` is just a symbol, it doesn't contain any value in this context and in fact gets replaced by 'z after the `(= (car x) 'z)` assignment. The real reason why it assigns is that `(car x)` doesn't get evaluated at all because `=` is a macro. – enrey Jan 13 '15 at 17:03
  • @enrey ok, TBH the last sentence is not really "wrong", it's correct, but it's dangerously misleadingly explaining something seemingly very close but actually totally unrelated to what the question is asking. – enrey Sep 08 '15 at 14:45