17

I want to allow the user to choose their own command in the "customize" emacs backend (and generally be able to store an executable form name in a variable) but this does not work :

    (defun dumb-f ()
    (message "I'm a function"))

    (defvar my-function "dumb-f")

    (my-function)
    ==> Debugger entered--Lisp error: (invalid-function "dumb-f")

    (setq my-function 'dumb-f)

    (my-function)
    ==> Debugger entered--Lisp error: (invalid-function "dumb-f")

I tried various forms, but still no luck, and I'm having a hard time searching for it, I get kilopages of results about functions and variables, but none about how to put the former in the latter..?

yPhil
  • 8,049
  • 4
  • 57
  • 83

3 Answers3

32

Note that in Emacs Lisp, symbols have a value cell and a function cell, which are distinct. When you evaluate a symbol, you get its value. When you evaluate a list beginning with that symbol, you call its function. This is why you can have a variable and a function with the same name.

Most kinds of assignment will set the value (e.g. let, setq, defvar, defcustom, etc...) -- and as ryuslash shows you can assign a function as a value and call it via funcall -- but there are also ways to assign to a symbol's function cell directly using fset (or flet, defalias, etc)

(fset 'my-function 'dumb-f)
(my-function)

In your case I would use ryuslash's answer (except you need to use defcustom rather than defvar if you want it to be available via customize).

Also, regarding "I'm having a hard time googling for it"; always remember that Emacs is self-documenting, and among other things contains a good manual complete with index (well, more than one manual, in fact). So even if Google remains your first port of call, it shouldn't also be your last if you can't find what you're looking for. From the contents page of the elisp manual you can navigate to "Functions" and then "Calling functions" and you will be told about funcall almost immediately.

phils
  • 71,335
  • 11
  • 153
  • 198
  • My example was badly choosen, sorry : I want to use customize to, say let the user choose its mail program, like so : `(defcustom my-mail-program "gnus" "Mail client command. Example : wl" :type 'string :group 'mail-bugger)` I cannot get to execute (my-mail-program)..? – yPhil Apr 01 '12 at 22:04
  • 1
    So you should use `:type 'function` rather than `'string`, with a default value of `'gnus` rather than `"gnus"`, and then you would use `(funcall my-mail-program)`. Make sure you understand the difference between a string and a symbol. – phils Apr 02 '12 at 02:06
  • This is a good tip, however it stores the _symbol_ `dumb-f` in the function slot of symbol `my-function`. This means that if you overwrite the definition of `dumb-f`, `my-function` will now point to the new definition. To avoid this, use Alekseyev's solution: `(fset 'my-function (symbol-function 'dumb-f))`. – hraban Mar 22 '20 at 01:36
20

To run a function stored in a variable you can use funcall

(defun dumb-f ()
  (message "I'm a function"))

(defvar my-function 'dumb-f)

(funcall my-function)
==> "I'm a function"
ryuslash
  • 1,232
  • 11
  • 11
  • 1
    Note that this doesn't store the function, it stores the symbol `dumb-f` which, when passed to `funcall`, is then evaluated for its function value. This distinction matters if you overwrite the function: you will now call the new one. So if you want to "backup" the original function to call it later, you need to use @arseniy-alekseyev's answer. – hraban Mar 22 '20 at 01:32
3

@phils' great answer mentions various ways of setting a symbol's function definition, but I also needed a way of getting it.

To get a symbol's value as a function you can use the function symbol-function.

For example:

; remember the old value of 'foo as a function
(set 'foo-backup (symbol-function 'foo))
; change it, to experiment or whatever
(defun foo () whatever)
; revert it back to what it was
(fset 'foo foo-backup)

And indeed the emacs manual was helpful here, in particular:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Components.html

https://www.gnu.org/software/emacs/manual/html_node/elisp/Function-Cells.html