我们最近开始在课堂上学习Common Lisp。我正在尝试实现一个带有两个列表并输出其公共元素的函数。我们仅限于使用基本功能表格。
(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))。就我能理解它而言,似乎期待一种函数类型。
错误:TYPE-ERROR:DATUM(CAR L1):预期类型功能 快速链接打开:do(si :: use-fast-links nil)用于调试 由COND发出信号。 TYPE-ERROR:DATUM(CAR L1):预期类型功能
在COND打破。
答案 0 :(得分:0)
你的问题是由于在cond
的第二个分支中,当关于两个car
s相等的条件为真时计算的表达式是:{{1 }}。
这里有一个列表,其中包含两个元素((car L1) (myCommon (cdr L1) L2)))
,位于需要表单的位置(即具有((car L1) (myCommon...))
结构的列表)。因此系统会发出错误,因为(function argument1 argument2 ...)
不是函数。我想你想要做的是生成一个包含这两个参数的新列表,例如可以通过“consing”获取它们,就像在(car l1)
中一样,这就是你的函数重写:
(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)
重复出现)。因此,您需要在必要时更正“消耗”第二个参数的功能。