В elisp, как мне поместить функцию в переменную?
Я хочу разрешить пользователю выбирать свою собственную команду в "настройке" emacs-сервера (и, как правило, иметь возможность сохранять имя исполняемой формы в переменной), но это не работает:
(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")
Я пробовал разные формы, но мне все равно не повезло, и мне трудно найти его, я получаю килобайты результатов о функциях и переменных, но никто о том, как поставить первое в последнем.?
Ответы
Ответ 1
Обратите внимание, что в Emacs Lisp символы имеют ячейку значений и ячейку функций, которые различны. Когда вы оцениваете символ, вы получаете его значение. Когда вы оцениваете список, начинающийся с этого символа, вы вызываете его функцию. Вот почему вы можете иметь переменную и функцию с тем же именем.
В большинстве видов присваивания задается значение (например, let
, setq
, defvar
, defcustom
и т.д.)), и, как показано на ryuslash, вы можете назначить функцию как значение и вызов это через funcall
- но есть также способы назначить ячейку символьной функции непосредственно с помощью fset
(или flet
, defalias
и т.д.)
(fset 'my-function 'dumb-f)
(my-function)
В вашем случае я бы использовал ответ ryuslash (за исключением того, что вам нужно использовать defcustom
, а не defvar
, если вы хотите, чтобы он был доступен через customize
).
Кроме того, в отношении "У меня тяжелое время для поиска"; всегда помните, что Emacs является самодокументированным, и среди прочего содержит хорошее руководство с индексом (на самом деле, более одного руководства). Поэтому, даже если Google остается вашим первым портом захода, он также не должен быть последним, если вы не можете найти то, что ищете. На странице содержимого руководства elisp вы можете перейти к "Функции", а затем "Функции вызова", и вам будет сообщено о funcall
почти сразу.
Ответ 2
Чтобы запустить функцию, сохраненную в переменной, вы можете использовать funcall
(defun dumb-f ()
(message "I'm a function"))
(defvar my-function 'dumb-f)
(funcall my-function)
==> "I'm a function"
Ответ 3
Отличный ответ @phils упоминает различные способы задания определения функции символа, но мне также нужен был способ ее получения.
Чтобы получить значение символа как функцию, вы можете использовать функцию symbol-function
.
Например:
; 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)
И действительно, руководство emacs было полезно здесь, в частности:
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