Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when I use a plain setf statement in LISP?

I know that when you want to make a dynamic/global binding in Lisp, you use either defparameter or defvar. I also know that you can make lexical bindings, well, almost everywhere, using defun argument lists or let statements.

What I'm wondering is what exactly it is I make when I make a statement like this where x was not declared or used anywhere else in the code:

(setf x 10 )

This appears to work fine, and x doesn't seem to behave like a lexical variable. Is it actually a dynamic global, the same as if I'd used defparameter or defvar, or is it something else entirely?

like image 332
Gearov Avatar asked Dec 26 '12 09:12

Gearov


People also ask

What does Setf do in Lisp?

setf is actually a macro that examines an access form and produces a call to the corresponding update function. Given the existence of setf in Common Lisp, it is not necessary to have setq, rplaca, and set; they are redundant. They are retained in Common Lisp because of their historical importance in Lisp.

What is the difference between Setf and SETQ?

1. What is the difference between setf and setq? Explanation: Setq is used only for setting the values of symbols but setf can be used for anything. Setf can be used for setting value of any data-type and not only symbols.

What does SETQ mean in Lisp?

Sets the value of a symbol or symbols to associated expressions. (setq sym expr [sym expr]...) This is the basic assignment function in AutoLISP. The setq function can assign multiple symbols in one call to the function.

What are generalized variables?

Generalized variables are analogous to lvalues in the C language, where ' x = a[i] ' gets an element from an array and ' a[i] = x ' stores an element using the same notation. Just as certain forms like a[i] can be lvalues in C, there is a set of forms that can be generalized variables in Lisp.


1 Answers

What it actually does is unspecified in the ANSI Common Lisp standard.

Generally I prefer any CL implementation to just set the dynamically bound value or global value. It should not to do anything else. CMUCL by default seemed to think that it was a good idea to declare the symbol special then. But that was a bad idea, since there was no obvious way to get rid of a global special declaration.

So, typically I would expect something like this (here, LispWorks):

CL-USER 66 > (defun foo () (setf x44 10))
FOO

The global variable is still unbound:

CL-USER 67 > x44

Error: The variable X44 is unbound.
  1 (continue) Try evaluating X44 again.
  2 Specify a value to use this time instead of evaluating X44.
  3 Specify a value to set X44 to.
  4 (abort) Return to level 0.
  5 Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 68 : 1 > :top

Let's call the function:

CL-USER 69 > (foo)
10

Now it has a global value:

CL-USER 70 > x44
10

But the variable is not declared to be special (as it would be by DEFVAR or DEFPARAMETER). Here a lexical binding is established.

CL-USER 71 > (let ((x44 20)) (foo) x44)
20

When we declare the local variable to be special, then our function changes the binding:

CL-USER 72 > (let ((x44 20)) (declare (special x44)) (foo) x44)
10
like image 112
Rainer Joswig Avatar answered Jan 01 '23 20:01

Rainer Joswig