(lambda () ...) or #'(lambda () ...)

#’ 的用法好模糊, 好多人认为只是一个书写习惯, 大家怎么看?

我个人理解, 如果一个变量表示函数, 那么#‘是必要的,比如下面这个例子:

(defun test ()
  (message "This is a test"))

(defvar test "Hello world")

(defvar test1 nil)

(setq test1 test)

(funcall test1) ;=> funcall: Invalid function: "Hello world"

(setq test1 #'test)

(funcall test1) ;=> "This is a test"

但lambda的写法,那个更好一点,我就比较疑惑了:

(lambda () (message "Hello"))
'(lambda () (message "Hello"))
#'(lambda () (message "Hello"))

只要不出问题就可以。 lambda 还是建议用 sharp quote

lambda 最好不要 quote

Never hard quote a lambda, it impedes byte-compilation. 不要 hard quote 一个 lambda,那样会妨碍字节码编译。 —— emacs lisp style guide


;;; Good
(lambda (x) (car x))

;;; Ok, but redundant.
#'(lambda (x) (car x))

;;; Bad
'(lambda (x) (car x))
4 个赞

我发现个简单的办法:#' 后面的 lambda 高亮没了,所以一定有问题。

这个真心不错

现在这两者的效果一样,所以就没必要再 #' 了,以前1是有区别的,所以你会看到很多加 #' 的 lambda,这是历史遗留下来的。现在的 #' 用来 Quote 函数名,作为给 Byte Compiler 的提示,程序执行上跟 ' 没有区别。


1 大概 20 年前, 根据 elisp - When to sharp-quote a lambda expression? - Emacs Stack Exchange 的说法

2 个赞

黑科技呀, lambda 是一个宏, 返回 #'lambda

(defmacro lambda (&rest cdr)
  "Return a lambda expression.
A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is
self-quoting; the result of evaluating the lambda expression is the
expression itself.  The lambda expression may then be treated as a
function, i.e., stored as the function value of a symbol, passed to
`funcall' or `mapcar', etc.

ARGS should take the same form as an argument list for a `defun'.
DOCSTRING is an optional documentation string.
 If present, it should describe how to call the function.
 But documentation strings are usually not useful in nameless functions.
INTERACTIVE should be a call to the function `interactive', which see.
It may also be omitted.
BODY should be a list of Lisp expressions.

\(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"
  (declare (doc-string 2) (indent defun)
           (debug (&define lambda-list
                           [&optional stringp]
                           [&optional ("interactive" interactive)]
                           def-body)))
  ;; Note that this definition should not use backquotes; subr.el should not
  ;; depend on backquote.el.
  (list 'function (cons 'lambda cdr)))

不总是这样:如果 Byte Compiler 发现你在某些位置上用了 '(lambda ()) 还是会 byte compile 的,并给出提示:

(byte-compile
 (lambda ()
   (funcall '(lambda () 123))))
     => #[nil "\300\207" [123] 1]

这里的 lambda 还是 byte compile 了。但同时也给出了下面的提示:

(lambda nil …) quoted with ’ rather than with #’

funcallapply 有这样的效果,但一般的函数就没有这个效果:

(byte-compile
 (lambda ()
   (list '(lambda () 123))))
     => #[nil "\300C\207" [(lambda nil 123)] 1]

Recent Elisp changes have rather gone the other way (adding a # rather than removing them). Part of the reason is that lexical-binding gives different semantics to ‘(lambda …) and #’(lambda …), other part is that cl-flet and cl-labels also give different semantics to 'foo and #'foo.

Finally, if you keep the # part, the byte-compiler will be able to check that you spelled the function correctly (and warn you if that function is not known to exist).

    Stefan
1 个赞

我是……一般不加……

我想让编译器确定的知道这是一个函数的时候,才会加上

再往下走一层, 区分#'和’的写法, 是要将底层Memory的区分data与function的硬件思路, 拿来当固定思维模式, 并且一以贯之, 始终在思维上严格区分.