【问题标题】:In elisp, how do I put a function in a variable?在 elisp 中,如何将函数放入变量中?
【发布时间】:2012-04-14 02:54:10
【问题描述】:

我希望允许用户在“自定义”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")

我尝试了各种形式,但仍然没有运气,而且我很难找到它,我得到了关于函数和变量的数千页结果,但没有关于如何将前者放入后者..?

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    请注意,在 Emacs Lisp 中,符号有一个值单元和一个函数单元,它们是不同的。当你评估一个符号时,你会得到它的。当您评估以该符号开头的列表时,您调用它的函数。这就是为什么你可以拥有同名的变量和函数。

    大多数类型的赋值都会设置值(例如letsetqdefvardefcustom 等...)——正如 ryuslash 所示,您可以将函数赋值为值并调用它通过funcall——但也有一些方法可以直接使用fset(或fletdefalias等)分配给符号的功能单元

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

    在你的情况下,我会使用 ryuslash 的答案(除非你需要使用 defcustom 而不是 defvar,如果你希望它可以通过 customize 使用)。

    另外,关于“我很难用谷歌搜索它”;永远记住,Emacs 是自文档化,除此之外,它还包含一本很好的带有索引的手册(事实上,不止一本手册)。因此,即使 Google 仍然是您的第一个停靠港,但如果您找不到所需内容,它也不应该是您的最后一个停靠港。从 elisp 手册的内容页面,您可以导航到“函数”,然后导航到“调用函数”,您将立即被告知 funcall

    【讨论】:

    • 我的例子选错了,对不起:我想使用自定义,比如让用户选择它的邮件程序,就像这样:(defcustom my-mail-program "gnus" "Mail client command. Example : wl" :type 'string :group 'mail-bugger)我无法执行(我的邮件程序) ..?
    • 所以你应该使用:type 'function而不是'string,默认值为'gnus而不是"gnus",然后你会使用(funcall my-mail-program)。确保您了解字符串和符号之间的区别。
    • 这是一个很好的提示,但是它将 symbol dumb-f 存储在符号 my-function 的函数槽中。这意味着如果您覆盖dumb-f 的定义,my-function 现在将指向新定义。为避免这种情况,请使用 Alekseyev 的解决方案:(fset 'my-function (symbol-function 'dumb-f))
    【解决方案2】:

    要运行存储在变量中的函数,您可以使用funcall

    (defun dumb-f ()
      (message "I'm a function"))
    
    (defvar my-function 'dumb-f)
    
    (funcall my-function)
    ==> "I'm a function"
    

    【讨论】:

    • 请注意,这不存储函数,它存储符号 dumb-f,当传递给 funcall 时,然后对其函数值进行评估。如果您覆盖该函数,则此区别很重要:您现在将调用新函数。因此,如果您想“备份”原始函数以供以后调用,则需要使用@arseniy-alekseyev 的答案。
    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多