5

I am currently working my way through Graham's On Lisp and find this particular bit difficult to understand:

Binding. Lexical variables must appear directly in the source code. The first argument to setq is not evaluated, for example, so anything built on setq must be a macro which expands into a setq, rather than a function which calls it. Likewise for operators like let, whose arguments are to appear as parameters in a lambda expression, for macros like do which expand into lets, and so on. Any new operator which is to alter the lexical bindings of its arguments must be written as a macro.

This comes from Chapter 8, which describes when macros should and should not be used in place of functions.

What exactly does he mean in this paragraph? Could someone give a concrete example or two?

Much appreciated!

3
  • 1
    As an experience Lisper, I totally understand what that text is trying to say, only I cannot parse the actual text. If I run my finger down the middle of the paragraph and just skim it in 0.5 seconds, then it makes sense, but if I pick at the individual words and phrases then it sort of eludes me. Commented Mar 13, 2018 at 21:49
  • 1
    The "arguments" of a let do not appear in a lambda expression, for instance. What? Commented Mar 13, 2018 at 22:00
  • Are you saying it is poorly written? This paragraph was an example of a paragraph that no matter how many times I had read it, I still asked myself, "Whaaat?" Commented Mar 14, 2018 at 15:18

1 Answer 1

8

setq is a special form and does not evaluate its first argument. Thus if you want to make a macro that updates something, you cannot do it like this:

(defun update (what with)
  (setq what with))

(defparameter *test* 10)
(update *test* 20)        ; what does it do?
*test*                    ; ==> 10

So inside the function update setq updates the variable what to be 20, but it is a local variable that has the value 10 that gets updated, not *test* itself. In order to update *test* setq must have *test* as first argument. A macro can do that:

(defmacro update (what with)
  `(setq ,what ,with))

(update *test* 20)        ; what does it do?
*test*                    ; ==> 20

You can see exactly the resulting code form the macro expansion:

(macroexpand-1 '(update *test* 20))
; ==> (setq *test* 20) ; t

A similar example. You cannot mimic if with cond using a function:

(defun my-if (test then else)
  (cond (test then)
        (t else)))

(defun fib (n)
  (my-if (< 2 n) 
         n
         (+ (fib (- n 1)) (fib (- n 2)))))

(fib 3)

No matter what argument you pass you get an infinite loop that always call the recursive case since all my-if arguments are always evaluated. With cond and if the test gets evaluated and based on that either the then or else is evaluated, but never all unconditionally.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.