我试图理解lambdaEmacs Lisp中发现的概念.
在ielm,执行:
((lambda (x) (* x x)) 5)
Run Code Online (Sandbox Code Playgroud)
给了我们25,和
(let ((x 4)) (* x x))
Run Code Online (Sandbox Code Playgroud)
给了我们16.但是,当我这样做时:
(let ((f (lambda (x) (* x x)))) (f 7))
Run Code Online (Sandbox Code Playgroud)
它没有给我49,而是通知我:
*** Eval error *** Symbol's function definition is void: f
Run Code Online (Sandbox Code Playgroud)
不知道为什么,我确定语法是正确的,f是在let?中定义的?
使用cl-flet定义let-ed功能
我们可以真正做到这一点,而无需使用funcall.该cl模块包括Common Lisp的标准功能.我们先导入它:
(require 'cl)
Run Code Online (Sandbox Code Playgroud)
此后我们可以cl-flet用来定义我们的功能:
(cl-flet ((f (x) (* x x)))
(f 7))
Run Code Online (Sandbox Code Playgroud)
如果这不是重复,我会感到惊讶,但我在Stack Overflow上找不到它.在"Lisp-2"语言(例如,Emacs Lisp和Common Lisp)中,函数和变量有单独的名称空间.函数调用如下所示:
((lambda ...) ...) ; call the lambda function
Run Code Online (Sandbox Code Playgroud)
要么
(f ...) ; call the function binding of f
Run Code Online (Sandbox Code Playgroud)
如果要调用作为变量值的函数,则需要使用funcall或apply:
(apply f ...)
(funcall f ...)
Run Code Online (Sandbox Code Playgroud)
apply和funcall之间的区别在其他地方有很好的记录,但快速区别在于apply需要一个参数列表(在一些Lisp中,一个"可扩展的参数列表"),而funcall直接接受参数.例如,
(let ((f (lambda (a b) (+ a b))))
(funcall f 1 2) ; arguments directly
(apply f '(1 2))) ; arguments in a list
Run Code Online (Sandbox Code Playgroud)
在"Lisp-1"中,(如Scheme),您不需要funcall,因为只有一个空间可用于绑定.在Scheme中你可以做到:
(let ((f (lambda (a b) (+ a b))))
(f 1 2))
Run Code Online (Sandbox Code Playgroud)
Lisp-1和Lisp-2 之间的区别更多描述Lisp-1和Lisp-2有什么区别?.最大的区别在于系统何时看到函数调用,它如何确定要调用的函数.在Lisp-1中,变量具有值,而这就是全部.所以当系统看到类似的东西时:
(f ...)
Run Code Online (Sandbox Code Playgroud)
f是一个变量,唯一可以调用的是f的值.在Lisp-2中,系统试图调用f 的函数值,f 函数值不必与变量 f 的值有任何关系.起初这可能有点令人困惑,但在许多情况下它实际上非常方便,因为它使得用常见名称意外地模糊函数变得更加困难.例如,在Lisp-1中,你会看到许多人使用lst参数名而不是list,因为如果他们命名参数list,那么他们就不能在函数中使用(标准)list函数.
| 归档时间: |
|
| 查看次数: |
1351 次 |
| 最近记录: |