Elisp:在Let中绑定一个lambda并执行它

时间:2016-03-16 15:18:09

标签: emacs lisp elisp

我试图了解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 - ed函数

我们可以实际执行此操作而不使用funcallcl模块包含Common Lisp的标准函数。我们先导入它:

(require 'cl)

此后我们可以使用cl-flet来定义我们的功能:

(cl-flet ((f (x) (* x x)))
  (f 7))

1 个答案:

答案 0 :(得分:8)

如果这不是重复,我会感到惊讶,但我无法在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 ...)

应用 funcall 之间的区别在其他地方有详细记录,但快速区别在于应用需要参数列表(在一些Lisps,一个"可扩展的参数列表"),而 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,因为只有一个空间可用于绑定。在Scheme中你可以做:

(let ((f (lambda (a b) (+ a b))))
  (f 1 2))

Lisp-1和Lisp-2语言之间的区别在What is the difference between Lisp-1 and Lisp-2?中有更多描述。最大的区别在于系统何时看到函数调用,它如何确定要调用的函数。在Lisp-1中,变量具有值,而这些都是值。所以当系统看到类似的东西时:

(f ...)

f是一个变量,唯一可以调用的是f的值。在Lisp-2中,系统试图调用f的函数值,它不需要对变量 f的值进行任何操作。起初这可能有点令人困惑,但在许多情况下它实际上非常方便,因为它使得用通用名称意外地模糊函数变得更加困难。例如,在Lisp-1中,您会看到很多人使用lst作为参数名称而不是list,因为如果他们将参数命名为list,那么他们就无法&{ #39;在函数中使用(标准)函数list