Reputation: 3103
Early steps with macros and looking for clarification.
(defmacro nil! (x)
(list 'setf x nil))
Paul Graham writes on p169 of ANSI CL
nil!
,ntimes
andwhile
all have to be written as macros because all have to control the way in which their arguments are evaluated.
I looked at nil!
and thought, wait a minute, I want to try writing that as a function. Turned out he's right, as expected, but looking to pin down why. If I do
(defun nil!f (x)
(setf x nil))
(setf a 9)
(nil!f a)
; a is still 9, not nil
Having forced myself into this, I note this is an odd use of a function, because I would not normally setf
a parameter. If I was going to setf
in a function it would more likely be a global, not a parameter.
If I have it correct, the parameter x
creates a new lexical scope, which obscures the a
which i set at the top level. Meaning we can pass in a value to a function, but not a variable.
Whereas with macros we can deal in variables.
Of course we can do this
(defun nil!f-a ()
(setf a nil))
but now we lost the ability to pass in a variable to this particular function so it's a stumped version of original.
Hence the exact thing a macro allows you to do here is... ?
Second question, is this a true statement
"In CL you cannot pass a variable into a function"
Here I yield...
Upvotes: 3
Views: 532
Reputation: 139251
(defun nil!f (x)
(setf x nil))
If you do that, you can only set the new local variable x
to nil
. In plain Common Lisp it is not possible that this has another effect.
(defmacro nil! (x)
(list 'setf x nil))
(nil! foo)
Above expression will be replaced before execution with
(setf foo nil)
We can check that:
CL-USER 110 > (macroexpand-1 '(nil! foo))
(SETF FOO NIL)
Thus, since it is before execution, you can do all kinds of source (!) manipulation then.
"In CL you cannot pass a variable into a function"
That's true for lexical variables. Dynamically bound variables could be passed in as symbols.
Dynamically bound:
CL-USER 111 > (flet ((f (sym)
(symbol-value sym)))
(let ((a 10))
(declare (special a))
(f 'a)))
10
Lexically bound:
CL-USER 112 > (flet ((f (sym)
(symbol-value sym)))
(let ((a 10))
(f 'a)))
Error: The variable A is unbound.
Upvotes: 6