let and flet in emacs lisp

hatmatrix picture hatmatrix · Jul 29, 2009 · Viewed 9.6k times · Source

I don't know if you would call it the canonical formulation, but to bind a local function I am advised by the GNU manual to use 'flet':

(defun adder-with-flet (x)
  (flet ( (f (x) (+ x 3)) )
    (f x))
)

However, by accident I tried (after having played in Scheme for a bit) the following expression, where I bind a lambda expression to a variable using 'let', and it also works if I pass the function to mapcar*:

(defun adder-with-let (x)
  (let ( (f (lambda (x) (+ x 3))) )
    (car (mapcar* f (list x)) ))
)

And both functions work:

(adder-with-flet 3)   ==> 6
(adder-with-let 3) ==> 6

Why does the second one work? I cannot find any documentation where 'let' can be used to bind functions to symbols.

Answer

user58804 picture user58804 · Jul 29, 2009

Unlike Scheme, Emacs Lisp is a 2-lisp, which means that each symbol has two separate bindings: the value binding and the function binding. In a function call (a b c d), the first symbol (a) is looked up using a function binding, the rest (b c d) are looked up using the value binding. Special form let creates a new (local) value binding, flet creates a new function binding.

Note that whether value or function binding is used for lookup depends on the position in the (a b c d) function call, not on the type of the looked-up value. In particular, a value binding can resolve to function.

In your first example, you function-bind f (via flet), and then do a function lookup:

(f ...)

In your second example, you value-bind f to a function (via let), and then use a value lookup:

(... f ...)

Both work because you use the same kind of binding and lookup in each case.

http://en.wikipedia.org/wiki/Common_Lisp#Comparison_with_other_Lisps