#’ 的用法好模糊, 好多人认为只是一个书写习惯, 大家怎么看?
我个人理解, 如果一个变量表示函数, 那么#‘是必要的,比如下面这个例子:
(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))
我发现个简单的办法:#'
后面的 lambda 高亮没了,所以一定有问题。
这个真心不错
现在这两者的效果一样,所以就没必要再 #'
了,以前1是有区别的,所以你会看到很多加 #'
的 lambda,这是历史遗留下来的。现在的 #'
用来 Quote 函数名,作为给 Byte Compiler 的提示,程序执行上跟 '
没有区别。
1 大概 20 年前, 根据 elisp - When to sharp-quote a lambda expression? - Emacs Stack Exchange 的说法
黑科技呀, 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 #’
像 funcall
和 apply
有这样的效果,但一般的函数就没有这个效果:
(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
我是……一般不加……
我想让编译器确定的知道这是一个函数的时候,才会加上
再往下走一层, 区分#'和’的写法, 是要将底层Memory的区分data与function的硬件思路, 拿来当固定思维模式, 并且一以贯之, 始终在思维上严格区分.