Elisp:在 Let 中绑定 lambda 并执行它[重复]

问题描述 投票:0回答:1

我试图理解 Emacs Lisp 中的

lambda
概念。

ielm
中,执行:

((lambda (x) (* x x)) 5)

给我们

25
,和

(let ((x 4)) (* x x))

给我们

16
。然而当我这样做时:

(let ((f (lambda (x) (* x x)))) (f 7))

它没有给我

49
,而是告诉我:

*** Eval error ***  Symbol's function definition is void: f

不知道为什么,我确信语法是正确的并且 f 是在

let
中定义的?

使用

cl-flet
定义
let
编辑函数

我们可以实际上在不使用

funcall
的情况下做到这一点。
cl
模块包含 Common Lisp 中的标准函数。我们首先导入它:

(require 'cl)

此后我们可以使用

cl-flet
来定义我们的函数:

(cl-flet ((f (x) (* x x)))
  (f 7))
emacs lisp elisp
1个回答
19
投票

如果这不是重复的,我会感到惊讶,但我无法在 Stack Overflow 上轻松找到它。在“Lisp-2”语言(例如 Emacs Lisp 和 Common Lisp)中,函数和变量有单独的命名空间。函数调用看起来像:

((lambda ...) ...) ; call the lambda function

(f ...) ; call the function binding of f

如果你想调用作为变量值的函数,那么你需要使用funcall或apply:

(apply f ...)

(funcall f ...)

applyfuncall 之间的区别在其他地方有详细记录,但快速的区别是 apply 需要一个参数列表(在某些 Lisp 中,是一个“可扩展的参数列表”),而 funcall 则采用直接论证。例如,

(let ((f (lambda (a b) (+ a b)))) (funcall f 1 2) ; arguments directly (apply f '(1 2))) ; arguments in a list
在“Lisp-1”中(如Scheme),你不需要funcall,因为只有一个空间用于绑定。在计划中你

可以做:

(let ((f (lambda (a b) (+ a b)))) (f 1 2))
Lisp-1 和 Lisp-2 语言之间的区别在

Lisp-1 和 Lisp-2 之间有什么区别?中有更多描述。最大的区别在于,当系统看到函数调用时,它如何确定要调用哪个函数。在 Lisp-1 中,变量有值,仅此而已。因此,当系统看到类似以下内容时:

(f ...)
f 是一个变量,唯一可能调用的是 f 的值。在 Lisp-2 中,系统尝试调用 f 的

函数值,这与变量 f 的值没有任何关系。一开始这可能会有点令人困惑,但在许多情况下它实际上非常方便,因为它使得更难意外地用通用名称混淆函数。例如,在 Lisp-1 中,您会看到很多人使用 lst

 作为参数名称而不是 
list
,因为如果他们将参数命名为 
list
,那么他们就无法使用(标准)函数
list
 在函数内。

© www.soinside.com 2019 - 2024. All rights reserved.