Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Create a Temporary Function in Emacs Lisp

Tags:

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?

like image 389
Cristian Avatar asked Apr 17 '10 05:04

Cristian


People also ask

How do I create a function in Emacs?

To define a function, we use the special form defun. It's followed by the function name and its arguments. The arguments are private, so it does not change anything outside the function. Any other symbol called inside a function will bring its value from outside since Elisp has global scope.

Is Emacs functional Lisp?

Emacs Lisp supports multiple programming styles or paradigms, including functional and object-oriented. Emacs Lisp is not a purely functional programming language since side effects are common. Instead, Emacs Lisp is considered an early functional flavored language.

Is Emacs Lisp the same as Lisp?

By default, Common Lisp is lexically scoped, that is, every variable is lexically scoped except for special variables. By default, Emacs Lisp files are dynamically scoped, that is, every variable is dynamically scoped.

Is Emacs Lisp a scripting language?

Emacs Lisp is a dialect of the Lisp programming language used as a scripting language by Emacs (a text editor family most commonly associated with GNU Emacs and XEmacs). It is used for implementing most of the editing functionality built into Emacs, the remainder being written in C, as is the Lisp interpreter.


2 Answers

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.

like image 105
Chris Johnsen Avatar answered Sep 20 '22 23:09

Chris Johnsen


Do (require 'cl) to pull in the Common Lisp package, then use flet instead of let:

(flet ((do-work (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)))) 
like image 42
Sean Avatar answered Sep 20 '22 23:09

Sean