2016-09-17 99 views
3

我明白,两者都用于临时更改函数的值。除了cl-flet是一个函数,cl-letf是一个宏,你什么时候使用它们呢?在emacs中,cl-flet和cl-letf有什么区别?

+1

这是什么'C-H F'告诉你吗? ** CL **手册('C-h i m cl')的节点**功能绑定**和**修改宏**告诉你什么? – Drew

+0

当然我已经检查过手册。我已阅读了关于这些功能的所有信息。恐怕我无法理解文档的内容。例如,对于'cl-flet':“创建临时函数绑定。绑定可以是递归的,并且范围是词法,但是在闭包中捕获它们只会在使用'词法绑定'的情况下起作用。武汉理工大学? – UndeadKernel

+0

有时需要更多的阅读(例如,在这种情况下,如果你不熟悉词汇绑定的话)。但是,如果您发现某些您认为错误或从文档中遗漏的内容,请考虑报告它,以便可以改进:'M-x report-emacs-bug'。应该在文档中详细说明使用'cl-flet'和表面上看起来类似的功能。 – Drew

回答

6

的绑定可以递归

如果函数定义调用本身的名字,该函数将被调用? (比较cl-fletcl-labels行为)。

作用域是词法...捕捉它们倒闭......

阅读有关词法绑定/范围VS动态绑定/范围。

cl-letf可以用于设置动态绑定函数值,通过使用(symbol-function 'FUNC) PLACE的某些FUNC。这与已弃用的flet类似。

可以指定任何支持的PLACE,但对于函数绑定,cl-letf不是只有

你什么时候使用它们?

当您想临时定义(或覆盖)一个函数。您对任何给定用例所需的范围规则将决定您将使用哪个选项。


  • (cl-flet ((FUNC ARGLIST BODY...) ...) FORM...)

    FUNC是可见的只是形式上的代码。

  • (cl-labels ((FUNC ARGLIST BODY...) ...) FORM...)

    FUNC可见既在形式代码,并在FUNC自己的身体的代码。直到身体已经完成正在评估

  • (cl-letf (((symbol-function 'FUNC) VALUE) ...) BODY...)

    FUNC是可见的绝对一切。


一些(相当做作)的例子......

在第一个例子中,我们定义的临时功能递归 - 它自称 - 因此我们使用cl-labels

(nb这不是一个强大的析因实现;它仅用于演示目的。)

(defun my-factorial (number) 
    "Show the factorial of the argument." 
    (interactive "nFactorial of: ") 
    (cl-labels ((factorial (n) (if (eq n 1) 
           1 
           (* n (factorial (1- n)))))) 
    (message "Factorial of %d is %d" number (factorial number)))) 

如果更改cl-labelscl-flet你只要内(factorial (1- n))评估得到一个错误,因为我们暂时的功能,无功能factorial是已知的。

如果你是再定义一个全局factorial功能无条件地返回值1

(defun factorial (n) 1) 

然后通过cl-flet定义的factorial功能会看到当它调用factorial,并my-factorial会计算(* n 1)作为任何参数的值n

当不需要递归,cl-flet是蛮好用的:

(defun my-square (number) 
    "Show the square of the argument." 
    (interactive "nSquare of: ") 
    (cl-flet ((square (n) (* n n))) 
    (message "Square of %d is %d" number (square number)))) 

两个cl-labelscl-flet提供词法范围的功能,唯一可见这些宏调用的机构内编写的代码;并且特别是而不是的任何其他功能的代码,我们可能是,调用

如果你正在定义一个辅助函数,比如上面的例子,词法作用域可能就是你想要的,因为你有一个合理的机会只能在宏体内调用你的帮助器。

但是,如果您正试图暂时将覆盖这个现有的函数,那么您将需要调用的函数来查看覆盖。在这种情况下,您需要重写动态范围。

在过去flet是提供临时功能动态范围的方式,但flet现在已不倾向于使用cl-letf用的(symbol-function 'FUNC)

在下面的例子“地方”的,则乘法函数被重写,动态范围意味着my-squaremy-factorial将会看到并使用我们对乘法的临时定义。

(defun my-bad-square() 
    "Maths gone wrong." 
    (interactive) 
    (cl-letf (((symbol-function '*) '+)) 
    (call-interactively 'my-square))) 
(defun my-bad-factorial() 
    "More maths gone wrong." 
    (interactive) 
    (cl-letf (((symbol-function '*) 
      (lambda (x y) (- x y)))) 
    (call-interactively 'my-factorial))) 
+0

您能否指出我在PLACE定义的文档部分?从cl-letf的文档中我不清楚,我可以用作PLACE的具体用途。 – UndeadKernel

+1

从'C-h i g(elisp)通用变量'开始,然后阅读'设置通用变量'节点。 – phils