Emacs Lisp的macro和quote

我总结了一些自己在写elisp的时候在quote和macro上的挣扎,希望能帮到其他新手。

大佬能不能帮我看看有没有问题,写错了就尴尬了。

https://casouri.github.io/post/some-notes-on-emacs-lisp-eval-quote-and-macro/

先撤下来吧……问题太大了。

(defmacro m-m (var) `(message ,var))

卧槽,没想到问题这么大。等我回去撤下来

能说一下哪些地方有问题吗🙏🏼

这个quote加和不加的区别在哪?

传统 Lisp 的 defmacro 主体是一个返回列表的函数,返回的列表作为代码。(Scheme 的宏是另一回事)

(defmacro m2 (var) (message var))

(m2 "hello") ;; 这里展开的结果其实是 "hello",因为 (message "hello") 的返回值是 "hello"
;; 至于为啥你觉得生效了,是因为宏主体用 message 的副作用
;; 但副作用更加证明了你的错误,因为正常的宏展开不应该有副作用

;; 不信,你可以试试这个


(macroexpand '(m-m "hello")) ;; 我们用 macroexpand 来查看宏展开结果。
;; (message "hello")

(macroexpand '(m2 "v"))
;; "v"
;; 同时 minibuffer 会显示 v

1 个赞

喔喔喔,那么返回的list会被再一次eval对吗?因为平时用的macro都是会“执行”的。但是你说不应该有副作用,我就有点糊涂了……

会有 eval 是因为你在 eval 这个表达式,macro 做的只是展开,这个概念一定要明白

展开的过程可以有副作用,但不鼓励有。

所以说是展开后被当作普通的sexp eval,是这个意思吗。

是的。但相对于 sexp,我更倾向用 列表 这个词,因为在 Lisp 内部,代码只是用列表表示的数据,macro 就是用列表操作来操作代码

1 个赞

撤下来了。

有时间改改再po