什么时候应该使用尖引号?


10

我看到其他人的eLisp代码中使用了尖锐的引号,而我自己也使用了引号,但是我不清楚它们什么时候合适,什么时候不合适。

谁能确切说明何时应使用尖引号以及何时应使用普通单引号?


3
注意:这里或其他地方都有很多重复的问题
phils 17-10-8


1
我不认为这是重复的:emacs.stackexchange.com/questions/3595是关于#'与lambda一起使用的(答案基本上是“从不”),而@izkon的问题适用于将#'符号应用于符号。
Stefan's

Answers:


12

#'只是简写function,就像'简写quote

您可以在希望向字节编译器,解释器或人工阅读器表明其自变量为(被视为)函数的地方使用它。

在许多情况下,上下文决定了参数的处理方式,例如,如果仅引用(使用quote')而不是使用#'(或function),则如何处理。例如,在仅将符号用作symbol-function属性的情况下(即,将其用作函数),您可以仅传递符号(例如,将其引号或传递其值为符号的变量)。

但是,如果您确实#'在这样的上下文中使用,有时代码会更清晰。即使Emacs-Lisp本身理解在这种情况下将符号用作功能,对于人类的代码阅读者来说也可能有助于强调这一点。

在其他一些Lisps中,简单引号(用')或未引号的lambda形式的处理可能与在函数位置使用function#')引用时的用法不同。但不是在Emacs Lisp中。在Emacs Lisp中,您不需要引用(使用'#')要作为函数(而不仅仅是列表)的lambda形式。如果您确实希望将其仅作为列表,汽车lambda等处理,则将其引号(带有'),以下示例对此进行了说明。

来自(省略号)匿名函数

-特殊形式: function function-object

此特殊形式返回FUNCTION-OBJECT而不评估它。

在此,它类似于quote(* note Quoting::)。但是,与不同 quote,它还用作Emacs评估程序和字节编译器的注释,该注释FUNCTION-OBJECT旨在用作功能。假设FUNCTION-OBJECT是有效的lambda表达式,则有两个作用:

•将代码按字节编译时,将FUNCTION-OBJECT被编译为字节码功能对象(*请注意Byte Compilation::)。

•启用词法绑定时,FUNCTION-OBJECT将转换为闭包。*注意关闭::。

读取语法#'是使用的简写function。以下形式都是等效的:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

在下面的示例中,我们定义一个change-property函数,该函数将一个函数作为其第三个参数,然后是一个通过将其传递给匿名函数来double-property 使用的change-property函数:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

请注意,我们不引用该lambda表格。

如果编译上面的代码,还将编译匿名函数。例如,如果您通过将匿名函数引用为列表来构造匿名函数,则不会发生这种情况:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

在这种情况下,匿名函数将作为lambda表达式保留在编译后的代码中。即使看起来像一个字节编译器,字节编译器也不能假定它是一个函数,因为它不知道 change-property打算将其用作函数。


9

#'(aka function)可以在的前面使用,(lambda ...)但在那里是多余的,因此真正有意义的唯一地方是在符号的前面,如中所示#'car。在elisp的,#'car并且'car几乎完全相等的,所以的主要目的之一是简单地记录了意向(即指示谁读取这个代码,您打算使用这个符号作为一个功能)。但是,在某些情况下,差异更大:

  • 字节编译器利用了本文记录的意图,在编写#'car时将检查它是否car作为一个函数存在,如果找不到,它会发出警告,就像调用该函数一样。 。
  • cl-flet和中cl-labels,只能#'f引用本地定义的函数f,因为'f仍将引用全局符号f(以及可能存储在其symbol-function插槽中的任何函数)。例如

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.