Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lexical Bindings in Common Lisp Macros

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!

like image 294
MadPhysicist Avatar asked Mar 12 '18 21:03

MadPhysicist


People also ask

What are macros in Lisp?

A macro is an ordinary piece of Lisp code that operates on another piece of putative Lisp code, translating it into (a version closer to) executable Lisp.

How are macros implemented in Lisp?

During a macroexpansion phase, the Lisp expression will be passed to the macro function. This macro function can do arbitrary computation at macroexpansion time. The result of this call has to be again Lisp code. This Lisp code then is what the interpreter or compiler sees and executes or compiles.

What is binding in Lisp?

A binding is a pairing of an identifier with a location in which a Lisp object may be placed.

How can you define macros in Lisp give an example?

that takes arguments and returns a LISP form to be evaluated. It is useful when the same code has to be executed with a few variable changes. For example, rather than writing the same code for squaring a number, we can define a macro that holds the code for squaring.


1 Answers

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.

like image 67
Sylwester Avatar answered Oct 13 '22 11:10

Sylwester