超过1行代码的宏

时间:2013-02-18 05:32:17

标签: lisp common-lisp

我正在学习Common Lisp的宏系统,突然发现了一个问题

(defun hello () (format t "hello ~%")) 
(defun world () (format t "world ~%"))
(defmacro call-2-func (func1 func2)
  `(,func1)
  `(,func2))

(macroexpand-1 '(call-2-func hello world)) 
(WORLD) 
T

好。为什么我不能只从一个宏生成2个LoC?我该如何解决? ( progn将无法在更复杂的情况下工作......

2 个答案:

答案 0 :(得分:9)

您的宏只需返回一个表单,该表单将调用这两个函数 而是生成两种形式(并且只使用最后一种形式。)

尝试:

(defmacro call-2-func (func1 func2)
  `(progn (,func1) (,func2)))

或者如果您不想仅限于2个功能:

(defmacro call-funcs (&rest funcs)
  `(progn ,@(mapcar #'list funcs)))

答案 1 :(得分:0)

在上面的内容中似乎并不清楚,所以让我添加...是的,您可以从宏返回2行代码,但记住函数和宏通常只返回1个值。您可以在函数中计算多个值,但它只返回最后一个值。下面的这个函数只返回值-2(它仍然计算值-1,它对值-1没有任何作用)。

(defun myfun () (compute-value-1) (compute-value-2))

如果要返回2个值,可以将它们包装在列表(或其他结构)中,也可以使用#'值返回多个值。

在这种情况下,除非在列表中包装多个值或使用#'值,否则宏只能返回一个语句。它返回的内容也必须是正确的lisp代码,通常用PROGN

完成
(defmacro call-2-func (func1 func2) `(PROGN (,func1) (,func2)))

如果您使用

(defmacro call-2-func (func1 func2) `(,func1) `(,func2))

然后你的宏计算2个值,但它只返回最后一个。 (正如您在上面的宏扩展中看到的那样)

你可以通过一个defun来轻松地看到这个,它可以计算2个值但只返回最后一个值。

(defun myname () 1 2)

使用VALUES会有点奇怪。

(defmacro tttt () '(values (one) (one)))
(tttt)
1
1