我试图了解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函数
我们可以实际执行此操作而不使用funcall
。 cl
模块包含Common Lisp的标准函数。我们先导入它:
(require 'cl)
此后我们可以使用cl-flet
来定义我们的功能:
(cl-flet ((f (x) (* x x)))
(f 7))
答案 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
。