tags:

views:

398

answers:

2

Greetings. I wonder if there is an emacs lisp veteran out there -

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

I am wondering if anyone knew why the second one works because I cannot find any documentation where 'let' can be used to bind functions to symbols?

Thanks! Stephen (P.S. I originally posted this on Emacs Help forums but got no reply so thought I'd hit up a different community - is that still called cross-posting?)

+2  A: 

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.

Trey Jackson
Thanks for your response! Together with zielaj's explanation I see how this 'eval' thing also works. Yes, flet appears to be in the cl extension; I had originally read that (require 'cl) was needed before using flet but I guess in the newer emacs this is no longer the case...
Stephen
+6  A: 

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 (flet), and then do a function-lookup: (f ...)

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

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

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

Thanks for the explanation! I see, it is a distinction between value-lookup and function-lookup. I was familiar with the convention of having separate namespaces for functions and variables but couldn't connect that with how a function bound as a variable could be called by mapcar*.
Stephen