我必须用普通的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/

10-11 23:02
查看更多