Early steps with macros and looking for clarification.
(defmacro nil! (x)
(list 'setf x nil))
Paul Graham writes on p169 of ANSI CL
nil!,ntimesandwhileall 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...
(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With