How to Create a Temporary Function in Emacs Lisp
elisp, emacs
Solution
Like other lisps (but not Scheme), Emacs Lisp has separate namespaces for variables and functions (i.e. it is a ‘Lisp2’, not a ‘Lisp1’; see Technical Issues of Separation in Function Cells and Value Cells for the origin and meaning of these terms).
You will need to use `funcall` or `apply` to call a lambda (or other function) that is stored in a variable.
(cond (test-1 (funcall do-work 'a 'b 'c))
(test-2 (funcall do-work 'i 'j 'k))
Use `funcall` if you will always send the same number of arguments. Use `apply` if you need to be able to send a variable number of arguments.
The internal mechanism is that each symbol has multiple “cells”. Which cell is used depends on where the symbol is in an evaluated form. When a symbol is the first element of an evaluated form, its “function” cell is used. In any other position, its “value” cell is used. In your code, `do-work` has the function in its value cell. To access it as a function you use `funcall` or `apply`. If it were in the function cell, you could call it directly by using its name as the car of an evaluated form. You can accomplish this with `flet` or `labels` from the cl package.
Problem
I'm making some tedious calls to a bunch of functions, but the parameters will be determined at runtime. I wrote a simple function to keep my code DRY but giving it a name is unnecessary. I don't use this function anywhere else. I'm trying to do it the way I would in Scheme, but I get a `void-function` error: ``` (let ((do-work (lambda (x y z) (do-x x) (do-y y) ;; etc ))) (cond (test-1 (do-work 'a 'b 'c)) (test-2 (do-work 'i 'j 'k)))) ``` I could stick it all into an `apply` (e.g., `(apply (lambda ...) (cond ...))`) but that isn't very readable. Is there a better way?