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
I did a quick search of the Emacs lisp manual and couldn't find any reference to 'flet
, which isn't terribly surprising since that is a part of cl
- the common-lisp package.
let will do a local binding as well, but it won't bind to the "function cell" for that symbol.
i.e. This works:
(let ((myf (lambda (x) (list x x))))
(eval (list myf 3)))
but
(let ((myf (lambda (x) (list x x))))
(myf 3))
fails with the error: "Lisp error: (void-function myf)"
flet
on the other hand, does do the binding to the function cell, so this works:
(flet ((myf (x) (list x x)))
(myf 3))
Notice the difference being that flet
allows you to use the symbol myf
directly, whereas the let
does not - you have to use some indirection to get the function out of the "value cell" and apply that appropriately.
In your example, the 'mapcar
' did the equivalent to my use of 'eval
.
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
You don't have to use flet
if you do not want to. You place a function in the function cell of a local symbol defined using let
as in the following example:
(let ((ALocalSymbol))
(fset 'ALocalSymbol (lambda (x) (* 2 x)))
(ALocalSymbol 4)
)
Evaluating this will return 8. Do notice the quote in front of ALocalSymbol
in (let ((ALocalSymbol))...)
. While setq
quotes symbols, fset
does not.
flet
is a syntactic sugar of sorts. Using a plain-old let
to define nil-valued symbols, allows you to choose which "cell" of a symbol to set. You could use setq
to set the symbol's value cell or fset
to set the function cell.
Hope this helps,
Pablo
@d11wq there is `funcall' for this purpose. The following works:
(defun adder-with-let (x)
(let ((f #'(lambda (x) (+ x 3))))
(funcall f 3)))
(adder-with-let 3) ;=> 6