当 elisp 中的宏控制流时

when macro control flow in elisp

when 宏的代码取自 subr.el

(defmacro when (cond &rest body)
  (declare (indent 1) (debug t))
  (list 'if cond (cons 'progn body)))

这里,最后一个形式很复杂,

(list 'if cond (cons 'progn body))

构造列表时,是否已经对condbody形式进行了评估? 为什么程序员在一个地方使用 list 而在另一个地方使用 cons?他们两个不都采用多种形式并列出一份清单吗?

(list 'if cond (.......))
(cons 'progn body)

宏在 code 上运行。因此,当宏 when 被扩展(即调用宏扩展函数)时,符号 condbody 将绑定到您编写的表达式(符号或列表)。

例如,如果您写

(when (plusp 1)
  (print 'yes)
  (+ 1 2 3))

使用绑定到的参数调用宏展开:

cond = (plusp 1)
body = ((print 'yes) (+ 1 2 3))

因此表达式

(list 'if cond (cons 'progn body))

疏散到

(let ((cond '(plusp 1))
      (body '((print 'yes) (+ 1 2 3))))
  (list 'if cond (cons 'progn body)))
==> (if (plusp 1) (progn (print (quote yes)) (+ 1 2 3)))

这正是您想要的。

最后,list and cons are quite different, please read their docs (C-h f list RET&c) and the fine manual

listcons的区别:

(list 'progn '((foo) (bar)))
;;=> (progn ((foo) (bar)))

(cons 'progn '((foo) (bar)))
;;=> (progn (foo) (bar))