I'm a Common Lisp beginner and came across this piece of code:
(let ((foo (list 42)))
(setf (rest foo) foo))
The REPL seem to just loop forever when trying to execute it.
I'm a Common Lisp beginner and came across this piece of code:
(let ((foo (list 42)))
(setf (rest foo) foo))
The REPL seem to just loop forever when trying to execute it.
Copyright © 2021 Jogjafile Inc.
What is
FOO?FOOis initially a fresh list,(42). In Lisp, lists are represented by cons cells, blocks of mutable memory containing each aCARand aCDRslot. Another way to print it is(42 . NIL), where theCARandCDRare on each side of the dot. This can also be pictured as follows:When you call
SETFwith the(rest foo)place and thefoovalue, you are saying that you want the cdr cell ofFOOto hold the valueFOO. In fact, this occurrence ofSETFis likely to macroexpand into a call toRPLACD.Why does the REPL loop forever?
The "P" part of the "REPL" (print) tries to print your circular structure. This is because
SETF's value is the one being returned from the form being evaluated, and the value returned bySETFis the value of its second argument, namelyFOO. Imagine you want to write a cons cell X with a naive algorithm:However, for
foo, step 4 will print the same structure, recursively, and will never terminate.What can you do?
Try setting
*PRINT-CIRCLE*to T first:And now, your REPL should be happy:
The "Sharpsign Equal-Sign" notation allows the reader to affect part of a form to a (reader) variable, like
#1=..., and reuse it afterwards, e.g.#1#. This make it possible to represent circular cross-references between data, either during reading or printing. Here, we can see that the variable#1#denotes a cons-cell, where theCARis 42 and theCDRis#1#itself.