我的代码输出有问题,我想我正在检查列表空值的条件。
我想要完成的问题是:编写一个函数vecmul
,它将两个简单的数字列表作为输入。 vecmul应该以坐标方式将这些列表相乘,因为可以乘以向量。假设两个列表的长度相同。 [例如,(vecmul '(2 3 4 5) '(1 4 5 2))
会返回(2*1 3*4 4*5 5*2)
或(2 12 20 10)
。您不得将mapcar
用于此功能]
到目前为止我已经
了(defun vecmul (list list2)
(cond ((null list) 0)
(t (cons (* (car list) (car list2))
(vecmul (cdr list) (cdr list2))))))
[170]> (setq l '(2 4 6))
(2 4 6)
[171]> (setq r '(1 3 5))
(1 3 5)
[172]> (vecmul l r)
(2 12 30 . 0)
我得到了正确的数字,只是列表中添加了“。”和列表末尾的“0”。我很确定这是因为我没有正确停止递归或不正常工作。我只是不完全确定如何纠正它。
答案 0 :(得分:4)
你几乎是对的。但是,当正确终止为0
时,您将使用nil
终止列表。此代码有效:
(defun vecmul (list list2)
(cond ((null list) nil)
(t (cons (* (car list) (car list2)) (vecmul (cdr list) (cdr list2))))))
当您致电(cons 1 2)
时,您获得的利弊单元格会写为(1 . 2)
。表示法(1 2 3 4 5)
只是(1 . (2 . (3 . (4 . (5 . nil)))))
的简写。如果最后一个增量单元格的cdr
为6
,而不是nil
,则会获得(1 . (2 . (3 . (4 . (5 . 6)))))
,缩短为(1 2 3 4 5 . 6)
。
答案 1 :(得分:4)
Neil Forrester回答了你的问题。
更多评论。在Lisp中使用现代名称:first
和rest
。
(defun vecmul (list1 list2)
(cond ((null list1) nil)
(t (cons (* (first list1) (first list2))
(vecmul (rest list1) (rest list2))))))
如果你有一个简单的真假决定,IF
可能会更好。由于涉及列表操作,我将其编写如下,而不是使用WHEN
。
(defun vecmul (list1 list2)
(if (null list1)
nil
(cons (* (first list1) (first list2))
(vecmul (rest list1) (rest list2)))))
最好使用实际代码中的循环结构或映射。如上所述,递归具有堆栈深度限制。循环没有那个限制。
(defun vecmul (list1 list2)
(loop for e1 in list1 and e2 in list2
collect (* e1 e2)))
或
(defun vecmul (list1 list2)
(mapcar #'* list1 list2))