求教:如何理解Elisp单引号

(require-package 'org-download) ;;这里需要使用单引号
(use-package pdf-tools ;; 这里不需要使用单引号
  :ensure t
  :mode ("\\.pdf\\'" . pdf-view-mode)
  :config
  (pdf-tools-install)
  (setq-default pdf-view-display-size 'fit-page)
  (setq pdf-annot-activate-created-annotations t))

为什么前者需要使用单引号,后者不需要使用单引号呢?

单引号是quote函数的简写

require 是个函数,所以参数会按照函数eval执行规则优先执行,所以你如果需要得到一个符号的话,就需要用quote函数,use-package可能是一个宏,参数执行顺序可能是特定的

1 个赞

也许应该看一下 use-package 的源码。如果 use-package 写的是双引号我倒不意外……

lisp 和其他语言还是比较不一样的。

use-package 是个宏。

(defmacro a (x)
  (format "%s" (type-of x)))

(a aaa) ;; => "symbol"

(defun b (x)
  (format "%s" (type-of x)))

(b aaa) ;; => error: (void-variable aaa)
(b 'aaa) ;; => "symbol"

在宏里拿到 symbol 之后,接下来怎么来处理就看你心情了,比如再给它前面加一个 '

(defmacro my-require-package (x)
  `(require-package ',x))

(macroexpand-1 `(my-require-package org-download))
;; => (require-package 'org-download)

use-package 的源码里有几处就是类似这样的处理。

单引号用来阻止求值,函数参数位置会执行,宏参数位置不会执行,(foo 'x) 如果 foo 是函数它得到的是一个符号 x,如果 foo 是宏它得到的是一个列表 (quote foo)

如果不明白为什么加引号,试着考虑不加会发生什么。

2 个赞

@BlindingDark @xuchunyang

原来如此,用了Emacs一年了,单引号一直没搞透,自己一直没用上宏,回头研究一下。

感谢