macro的冒号(:)开头参数是怎么用的?

我看到好多macro都有这么个冒号开头的参数(比如use-package的keywords和spacemacs|add-company-backends).

我想问的是这种参数应该怎么用?看了半天没看明白……

你是指keyword吧?cl-defmacro支持keyword。或者你也可以直接用&rest args获得所有的参数(包括keyword)然后手动处理。

(defmacro handle-keyword (&rest rest)
  `(let (current-key)
     (dolist (arg ',rest)
       (if (keywordp arg)
           (setq current-key arg)
         (pcase current-key
           (':a (print (1+ arg)))
           (':b (print (1- arg))))))))

(handle-keyword :a 1 :b 1)

2

0

这个是我抄doom-emacs的时候学的……

另外前面带冒号的symbol是self quoting的,就是跟tnil一样,evaluate的结果是自己。

(eval :hi)
:hi
2 个赞

好吧……

我实际上想抄spacemacs|add-company-backends, 但是不想要那么多的功能,然后改的时候迷糊了……

唔,不在意(require 'cl-lib)的话,用cl-defmacro是最简单的方法了。

use-packagespacemacs|add-company-backends 是不同的:

  • use-package一 key 多 value
  • spacemacs|add-company-backends一 key 一 value,想省事用 cl-defuncl-defmacro,不怕麻烦自行处理,本质上就是操作 plist。

use-package 的参数列表以前有帖子讨论过:

算是定制版的 plist,不过它的 keyword 是预先定义的,不能随意添加。

我在这里写了两个(固定 keyword 和任意 keyword)简单的模拟实现:给 use-package 添加新的(没实际作用的)关键词 - #5,来自 twlz0ne

1 个赞

我希望的就是一key一value……而且这个value也没什么奇怪的用途

事实上我想把purcell的这个操作

(with-eval-after-load 'company
  (add-hook 'xxx-mode-hook
            (lambda () (sanityinc/local-push-company-backend 'company-xxx))))

给提取出来,然后就一脚踏入macro的大坑里……

到现在我也不知道用不用macro了……

(cl-defmacro my-macro (&key foo bar)
  `(cons ,foo ,bar))

(my-macro :foo 1
          :bar 2)
;; => (1 . 2)

(cl-defun my-func (&key foo bar)
  (cons foo bar))

(my-func :foo 1
         :bar 2)
;; => (1 . 2)
2 个赞

这种应该叫做plist吧, 类似的plist-get:

(plist-get '(:test1 "aaa" :test2 "bbb") :test)
;; => nil
(plist-get '(:test1 "aaa" :test2 "bbb") :test1)
;; => "aaa"
(plist-get '(:test1 "aaa" :test2 "bbb") :test2)
;; => "bbb"
2 个赞