在列表中乘以数字(以坐标方式)而不使用Lisp中的mapcar

时间:2013-04-02 03:17:22

标签: list recursion lisp vector-multiplication

我的代码输出有问题,我想我正在检查列表空值的条件。

我想要完成的问题是:编写一个函数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”。我很确定这是因为我没有正确停止递归或不正常工作。我只是不完全确定如何纠正它。

2 个答案:

答案 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)))))的简写。如果最后一个增量单元格的cdr6,而不是nil,则会获得(1 . (2 . (3 . (4 . (5 . 6))))),缩短为(1 2 3 4 5 . 6)

答案 1 :(得分:4)

Neil Forrester回答了你的问题。

更多评论。在Lisp中使用现代名称:firstrest

(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))