2009-07-28 65 views
33

我不知道,如果你把它叫做规范的制定,但是结合本地函数,我由GNU手册建议使用“FLET”:让和FLET中的Emacs Lisp

(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

为了任何人试图这一点,注意`flet`可能不会在你使用emacs的版本,在这种情况下尝试`(需要“CL )`事先如下所述(`flet`是CommonLisp thingy)。 – Robert 2013-05-01 13:47:17

+0

哪个GNU手册推荐在这里使用`flet`? – Stefan 2013-06-27 15:05:40

+1

来自Emacs 25.1.1描述函数:flet自24.3起,此宏已过时;使用'cl-flet'或'cl-letf' – AAAfarmclub 2017-01-01 06:29:58

回答

37

与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

18

我做了快速搜索的Emacs口齿不清手动和找不到任何参考'flet,这还不是特别令人惊讶,因为这是一个cl部分 - common-lisp package

let也会做一个本地绑定,但它不会绑定到该符号的"function cell"

即这个工程:

(let ((myf (lambda (x) (list x x)))) 
    (eval (list myf 3))) 

(let ((myf (lambda (x) (list x x)))) 
    (myf 3)) 

失败,出现错误: “Lisp的错误:(空隙功能了Myf)”

flet,另一方面,确实做功能单元绑定,所以这个工程:

(flet ((myf (x) (list x x))) 
    (myf 3)) 

注意不同之处在于,flet允许您直接使用符号myf,而let不会 - 您必须使用某种间接方式将函数从“值单元格”中取出并适当地应用。

在你的例子中,'mapcar'和我使用的'eval等价。

+0

感谢您的回应!与zielaj的解释一起,我看到这个'eval'事物是如何工作的。是的,flet似乎在cl扩展中。我原本读到在使用flet之前需要(需要'cl'),但是我认为在更新的emacs中不再是这种情况... – hatmatrix 2009-07-29 10:50:08

7

@ d11wq存在就是为了这个目的`funcall”。以下作品:

(defun adder-with-let (x) 
    (let ((f #'(lambda (x) (+ x 3)))) 
    (funcall f 3))) 

(adder-with-let 3) ;=> 6 
0

您不必使用flet,如果你不想。你把一个函数使用let在下面的例子中定义的本地符号的功能细胞:

(let ((ALocalSymbol)) 
    (fset 'ALocalSymbol (lambda (x) (* 2 x))) 
    (ALocalSymbol 4) 
) 

评估这将返回8.不要注意到的ALocalSymbol前报价在(let ((ALocalSymbol))...)。而setq报价符号,fset没有。

flet是一种类型的语法糖。使用普通的let定义无符号的符号,可以让您选择要设置符号的哪个“单元”。您可以使用setq来设置符号的值单元或fset来设置函数单元。

希望这有助于

巴勃罗