我不知道你是否会把它称为规范公式,但是绑定一个本地函数我被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'可用于将函数绑定到符号。
答案 0 :(得分:40)
与Scheme不同,Emacs Lisp是 2-lisp ,这意味着每个符号都有两个独立的绑定:值绑定和函数绑定。在函数调用(a b c d)
中,使用函数绑定查找第一个符号(a
),使用值绑定查找其余符号(b c d
)。特殊格式let
创建一个新的(本地)值绑定,flet
创建一个新的函数绑定。
请注意,值或函数绑定是否用于查找取决于(a b c d)
函数调用中的位置,而不取决于所查看的类型提升价值。特别是,值绑定可以解析为起作用。
在第一个示例中,您将函数绑定f
(通过flet
),然后执行函数查找:
(f ...)
在第二个示例中,您将f
值绑定到函数(通过let
),然后使用值查找:
(... f ...)
两者都有效,因为在每种情况下都使用相同类型的绑定和查找。
http://en.wikipedia.org/wiki/Common_Lisp#Comparison_with_other_Lisps
答案 1 :(得分:19)
我快速搜索了Emacs lisp手册,找不到对'flet
的任何引用,这不是特别令人惊讶,因为它是cl
的一部分 - {{3} }。
common-lisp package也会执行本地绑定,但它不会绑定到该符号的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
的使用相同。
答案 2 :(得分:7)
@ d11wq为此目的有`funcall'。以下作品:
(defun adder-with-let (x)
(let ((f #'(lambda (x) (+ x 3))))
(funcall f 3)))
(adder-with-let 3) ;=> 6
答案 3 :(得分:0)
如果您不想,则不必使用flet
。将函数放在使用let
定义的本地符号的函数单元格中,如下例所示:
(let ((ALocalSymbol))
(fset 'ALocalSymbol (lambda (x) (* 2 x)))
(ALocalSymbol 4)
)
评估此项将返回8.请注意ALocalSymbol
中(let ((ALocalSymbol))...)
前面的引号。虽然setq
引用了符号,但fset
却没有。
flet
是一种语法糖。使用普通的let
来定义零值符号,允许您选择要设置的符号的“单元格”。您可以使用setq
设置符号的值单元格,或使用fset
设置功能单元格。
希望这有帮助,
巴勃罗