我必须用普通的Lisp编写递归宏。
我有一个在列表中搜索最大元素的函数。例如,它返回45
表示列表(2 4 6 42 5 45 3)
现在我要把它转换成递归宏。
这是我的代码:
(defmacro mymax (values)
(cond
((= (length values) 1) `(write (car ,values)))
((> (car values) (cadr values)) (mymax (list (car values) (cddr values))))
(t (mymax (cdr values)))
)
)
它不起作用。编译错误:“LIST不是实数”我试过不同的组合'`'和','-没有结果如何更正代码,使宏的结果为数字?
宏调用:
(write (mymax (list 3 5 6 7 8)))
或
(write (mymax (cons 3 5 6 7 8)))
或
(write (mymax '(3 5 6 7 8)))
所有这些调用都以相同的结果结束。
最佳答案
下面是函数MAX
的宏版本,当每个参数都是数字时,它会执行一些有用的操作:
(defmacro mymax (&rest numbers)
(flet ((all-number-list-p (list) ; local function
(and (listp list) ; it's a list
(numberp (first list)) ; the first number exists
(every #'numberp list)))) ; everything is a number
(if (all-number-list-p numbers) ; only numbers?
(cond ((null (rest numbers)) (first numbers)) ; one number
((> (first numbers) (second numbers)) : first is greater
`(mymax ,@(cons (first numbers) ; get rid of the second
(cddr numbers))))
(t ; second is greater
`(mymax ,@(rest numbers)))) ; get rid of the first
`(max ,@numbers)))) ; fallback, use MAX
例子:
CL-USER 23 > (macroexpand-1 '(mymax 4 1 3 2))
(MYMAX 4 3 2)
T
CL-USER 24 > (macroexpand-1 '(mymax 4 3 2))
(MYMAX 4 2)
T
CL-USER 25 > (macroexpand-1 '(mymax 4 2))
(MYMAX 4)
T
CL-USER 26 > (macroexpand-1 '(mymax 4))
4
T
CL-USER 27 > (mymax 4 1 3 2)
4
注意,当不是每个参数都是数字时,它只使用
MAX
:CL-USER 28 > (macroexpand-1 '(mymax a b 8 d))
(MAX A B 8 D)
关于recursion - Common Lisp中的递归宏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33159712/