40

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.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
hatmatrix
  • 42,883
  • 45
  • 137
  • 231
  • 1
    To anyone trying this out, note that `flet` might not be available in the version of emacs you are using, in which case try a `(require 'cl)` beforehand as mentioned below (`flet` is a CommonLisp thingy). – Robert May 01 '13 at 13:47
  • Which GNU manual recommends the use of `flet` here? – Stefan Jun 27 '13 at 15:05
  • 2
    From Emacs 25.1.1 Describe Function: flet This macro is obsolete since 24.3; use either `cl-flet' or `cl-letf' – AAAfarmclub Jan 01 '17 at 06:29

4 Answers4

46

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

itsjeyd
  • 5,070
  • 2
  • 30
  • 49
user58804
  • 581
  • 4
  • 4
  • 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*. – hatmatrix Jul 29 '09 at 10:46
21

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
  • 73,529
  • 11
  • 197
  • 229
  • 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... – hatmatrix Jul 29 '09 at 10:50
  • 5
    Before the `cl` extension was shipped with Emacs out of the box, how did people handle function definitions that needed to be declared with let-like semantics? Was it just accepted that eval is the way to do it? – d11wtq May 17 '13 at 11:28
9

@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
carltonf
  • 91
  • 1
  • 3
-2

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

  • 1
    This is entirely wrong, and binds the (single) global function cell for the interned symbol `ALocalSymbol`. (Only *value* cells are let-bound.) You could do this if you were creating a *new* (uninterned) symbol, instead of just let-binding (the value of) the interned symbol. – phils Jul 17 '17 at 21:12
  • For clarity: This code defines a function `ALocalSymbol` in the global function namespace. If a function by that name was defined already, it is clobbered. – phils Jul 17 '17 at 22:40
  • Note also that if you did create an uninterned symbol, `(ALocalSymbol 4)` would still be calling the interned symbol's function, so you would need to `funcall` (or similar) your uninterned symbol/function. – phils Jul 17 '17 at 22:50
  • I just realized that you guys are correct. I ended up creating a global symbol! Thnx for the clarification. This actually explains why some code I had written does not work correctly. – Pablo A Perez-Fernandez Jul 18 '17 at 15:34