我不知道你是否会把它称为规范公式,但绑定一个本地函数我被GNU手册建议使用'flet':
(defun adder-with-flet (x) (flet ( (f (x) (+ x 3)) ) (f x)) )
然而,偶然我尝试(在使用Scheme之后)下面的表达式,其中我使用'let'将lambda表达式绑定到变量,并且如果我将函数传递给mapcar*它也可以工作:
(defun adder-with-let (x) (let ( (f (lambda (x) (+ x 3))) ) (car (mapcar* f (list x)) )) )
这两个功能都有效:
(adder-with-flet 3) ==> 6 (adder-with-let 3) ==> 6
为什么第二个有效?我找不到任何文档,其中'let'可用于将函数绑定到符号.
与Scheme不同,Emacs Lisp是一个2-lisp,这意味着每个符号都有两个独立的绑定:值绑定和函数绑定.在函数调用中(a b c d)
,a
使用函数绑定查找第一个符号()b c d
,使用值绑定查找rest().特殊表单let
创建一个新的(本地)值绑定,flet
创建一个新的函数绑定.
请注意,值或功能是否用于查找绑定依赖于位置的(a b c d)
函数调用,而不是在类型查找到的价值.特别是,值绑定可以解析为起作用.
在第一个示例中,您将函数绑定f
(via flet
),然后执行函数查找:
(f ...)
在第二个示例中,您将值绑定f
到函数(via let
),然后使用值查找:
(... f ...)
两者都有效,因为在每种情况下都使用相同类型的绑定和查找.
http://en.wikipedia.org/wiki/Common_Lisp#Comparison_with_other_Lisps
我做了快速搜索的Emacs口齿不清手动和找不到任何提及'flet
,这并不令人惊奇,因为这是一部分cl
-的共LISP封装.
let
也将进行局部绑定,但它不会绑定到该符号的"功能单元".
即这是有效的:
(let ((myf (lambda (x) (list x x)))) (eval (list myf 3)))
但
(let ((myf (lambda (x) (list x x)))) (myf 3))
失败并出现错误:"Lisp error:(void-function myf)"
flet
另一方面,确实绑定到功能单元,所以这工作:
(flet ((myf (x) (list x x))) (myf 3))
注意区别是flet
允许你myf
直接使用符号,而let
不是 - 你必须使用一些间接来从"值单元格"中获取函数并适当地应用它.
在你的例子中,' mapcar
'相当于我的使用'eval
.
为了这个目的,@ d11wq有`funcall'.以下作品:
(defun adder-with-let (x) (let ((f #'(lambda (x) (+ x 3)))) (funcall f 3))) (adder-with-let 3) ;=> 6