【问题标题】:How to properly use lambda in the emacs lisp language?如何在 emacs lisp 语言中正确使用 lambda?
【发布时间】:2017-03-13 22:53:29
【问题描述】:

当我想执行以下代码时遇到问题:

    (defun sum1
      (lambda (n)
        (+ n 1)))

当我使用 M-x ielm 运行时,会出现下一条消息:

无效函数:(lambda (lambda (n) (+ n 1)) nil)

我想明确一点,虽然我可能会使用以下代码:

    (defun sum1(n)
      (+ n 1))

我想知道在这种情况下如何定义 lambda。

所有信息都被接受,我是新手。

【问题讨论】:

  • 你可以对defun进行宏扩展,看看它只是在做(defalias 'sum1 (lambda (n) (+ n 1)))
  • Lambda 用于匿名函数。目前还不清楚你在问什么。你可以有,例如。 (defun make-adder (n) (lambda (x) (+ x n))) 返回一个将 n 添加到数字的函数。您可以将匿名函数作为变量的值:(let ((adder (lambda (x) (+ x 2)))) ...)
  • 我试图为此写一个适合新手的答案,但我意识到真正的答案是:如果你想学习 lisp不要从 elisp 开始。而是从 Common Lisp(一种传统但比 elisp 更整洁的 lisp)、Scheme(一种更现代的 lisp)或其他东西(Clojure?)开始。 elisp 并没有什么问题,但它确实过时了:它的功能很好,但不是如何学习 Lisp,因为它只会让你感到困惑。 (如果你想知道如何破解 emacs,那么 elisp 是一个不错的起点。)
  • 我终于成功了,(eval '(defun sum1 () (function (lambda (n) (+ n 1))) t)¨ (funcall (sum1) 5) ; 6
  • @Rovaceni23 以防万一它仍然相关:您在此处使用eval 除了阻止有用的编译器警告和将lambda 包装在function 中之外应该没有任何影响@ 应该是完全多余的。

标签: lambda emacs lisp elisp


【解决方案1】:

lambda 创建一个函数,但没有给它一个名字。每当你需要创建一个函数时使用它,但不需要给它一个名字。一个很好的例子是一个比较函数,它只使用一次来对列表进行排序。

(let ((l (number-sequence 1 10)))
  (sort l (lambda (a b) (> a b)))) ;; reversed

defun 一个你永远不会再使用的函数可能会很烦人。想出一个名字需要一点点努力,而且你需要确保你没有覆盖一个现有的函数(这并不难,我通常在我的函数前面加上我的首字母)。

lambda (IMO) 的一个常见滥用示例是用于钩子。很多人会将lambdas 添加到钩子中,但是如果您查看钩子变量的值,就会发现一堆lisp 而不是可以在其上运行describe-function 的函数名。但更糟糕的是,您不能使用remove-hook,或者在编写或调试函数时重新定义函数。

【讨论】:

    【解决方案2】:

    defun 用于声明函数。

    scheme 中,您曾经声明一个变量并为其分配一个变量表达式,如下所示:(define x variable-expression),而在声明一个函数时,您曾经编写过类似 (define x function-expression) 的内容。 Ofc variable-expression 可以是先前声明的另一个变量或文字(即define x 5define x y)。

    对于函数表达式也是如此,但是在编写“文字”函数时,您可以使用这样的匿名函数:

    (define x (lambda (x) (....)))
    

    其中lambda (x) (...) 是一个函数表达式,它实际上返回一个函数并赋值给x。所以这种方式 x 被声明为一个函数。

    defun 实际上声明了一个函数,而不是 define 在方案中所做的变量。所以当你写的时候:

    (defun sum1
     (lambda (n)
       (+ n 1)))
    

    真正发生的是 sum1 被声明为没有参数的函数,它返回另一个函数,该函数实际上接受变量 n 并返回 n+1

    您真正想要的是将sum1 声明为一个函数,而不是一个返回另一个函数的函数,这是您使用@987654335 实际得到的@ 和 lambda 在同一个 sn-p 中。

    EDIT1:你可以像这样使用你的函数((sum1) 5)

    【讨论】:

    • 其实你需要(defun sum1 () (lambda ...)):你需要arglist。同样没有词法范围(elisp 默认没有),这个定义根本不起作用。
    • 这是一个很长的解释,但不是最清楚的。请告诉这个人如何解决他的问题\正确编写他的代码,就像上面@tfb 所做的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多