我们最近开始在类里面学习 Common Lisp。我正在尝试实现一个函数,它接受两个列表并输出它们的公共(public)元素。我们仅限于使用基本函数形式。
(defun myCommon(L1 L2)
(cond
((null L1) nil) ;;check if the first list is empty
((null L2) nil) ;;check if the second list is empty
((eq (car L1) (car L2)) ((car L1) (myCommon (cdr L1) L2)))
(t (myCommon (cdr L1) L2)) ;;if they are not the same, recurse myCommon with L1 as (cdr L1)
)
)
我的问题是我无法理解为什么它会导致类型错误(违规数据:(CAR L1))。据我所知,它似乎期待一种函数类型。
Error: TYPE-ERROR :DATUM (CAR L1) :EXPECTED-TYPE FUNCTION Fast links are on: do (si::use-fast-links nil) for debugging Signalled by COND. TYPE-ERROR :DATUM (CAR L1) :EXPECTED-TYPE FUNCTION
Broken at COND.
最佳答案
你的问题是因为在 cond
的第二个分支中,当两个 car
的条件相等时计算的表达式是true 是:((car L1) (myCommon (cdr L1) L2)))
。
这里有一个包含两个元素 ((car L1) (myCommon...))
的列表,位于需要 form 的位置(即带有像 (function argument1 argument2 ...)
这样的结构。所以系统给出了一个错误,因为 (car l1)
不是一个函数。我想你想做的是产生一个包含这两个参数的新列表,例如可以通过“consing”它们来获得,比如 (cons (car L1) (myCommon ...))
,所以这是你重写的函数:
(defun myCommon(L1 L2)
(cond ((null L1) nil) ;;check if the first list is empty
((null L2) nil) ;;check if the second list is empty
((eq (car L1) (car L2)) (cons (car L1) (myCommon (cdr L1) L2)))
(t (myCommon (cdr L1) L2)))) ;;if they are not the same, recurse myCommon with L1 as (cdr L1)
请注意,如果您尝试此函数,例如:(mycommon '(1 2 3) '(1 2 3 4)
,您会发现答案是 (1)
而不是 (1 2 3)
。这是因为您仅“使用”第一个参数(通过使用 (cdr L1)
对其进行重复)。所以,您需要在必要时更正函数“消耗”第二个参数。
关于runtime-error - 列表中的 Lisp 公共(public)元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43508915/