13.7 匿名函数

尽管函数通常通过 defun 定义并同时赋予名称,但有时使用显式的 lambda 表达式 —— 即 匿名函数(anonymous function) 会更为便捷。匿名函数可在任何能使用函数名的场景下生效,常被赋值给变量,或作为函数的参数使用;例如,你可以将一个匿名函数作为 function 参数传递给 mapcar,由 mapcar 将该函数应用到列表的每个元素上(see 映射函数)。相关实际应用示例,see describe-symbols example

若要定义用作匿名函数的 lambda 表达式,应使用 lambda 宏、function 特殊形式,或 #' 读取语法:

Macro: lambda args [doc] [interactive] body…

该宏会返回一个匿名函数,其参数列表为 args、文档字符串为 doc(若有)、交互式规范为 interactive(若有),函数体由 body 给出的若干形式构成。

例如,这个宏使得 lambda 形式几乎自引用:对一个首元素(CAR)为 lambda 的表达式进行求值,得到的值与该表达式本身几乎一样:

(lambda (x) (* x x))
     ⇒ #f(lambda (x) :dynbind (* x x))

在词法绑定下求值时,结果是一个类似的闭包对象,其中 :dynbind 标记会被捕获的变量所替换(see 闭包)。

lambda 表达式还有一个作用:它通过将 function 作为子程序使用(见下文),告知 Emacs 求值器与字节编译器其参数是一个函数。

Special Form: function function-object

这个特殊形式会返回 function-object 的函数值。在很多方面,它与 quote 类似(see 引用)。但与 quote 不同的是,它同时还向 Emacs 求值器和字节编译器标记:function-object 是 “intended to be used as a function(意图作为函数使用)”。 假设 function-object 是合法的 lambda 表达式,这会产生两个效果:

  • 代码被字节编译时,function-object 会被编译成字节码函数对象(see 字节编译)。
  • 启用词法绑定时,function-object 会被转换成闭包。See 闭包

function-object 是一个符号且代码被字节编译时,若该函数未定义或在运行时可能无法被识别,字节编译器会发出警告。

读取语法 #' 是使用 function 的简写形式。以下形式完全等效:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

在下面的示例中,我们定义了一个 change-property 函数,该函数接受一个函数作为第三个参数;随后定义了 double-property 函数,它通过向 change-property 传入一个匿名函数来使用该函数:

(defun change-property (symbol prop function)
  (let ((value (get symbol prop)))
    (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
  (change-property symbol prop (lambda (x) (* 2 x))))

请注意,我们并未对 lambda 表达式进行引用(quote)。

如果你编译上述代码,这个匿名函数也会被编译。但假如你是通过将匿名函数作为列表进行引用(quote)的方式来构造它,情况就不同了:

(defun double-property (symbol prop)
  (change-property symbol prop '(lambda (x) (* 2 x))))

在这种情况下,该匿名函数会以 lambda 表达式的形式保留在编译后的代码中。即便这个列表看起来像一个函数,字节编译器也无法认定它就是函数 —— 因为编译器并不知道 change-property 意图将其用作函数。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike