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?

Original source