一些风格要点:不要使用(not liste);而是使用(null liste) 或(endp liste),它们分别强调liste 要么是一个空列表,要么处理已经到达liste 的末尾。此外,当打算表示一个空列表时,请使用'();当意图表示布尔值 False 时使用 nil。
liste的元素是符号,x本身就是一个符号;需要将这些符号转换为序列,以便评估符号的最终字符。 string 将完成这项工作。但是这里的OP代码有两个问题:length带有一个序列参数,所以(car liste)的值也必须用string转换;在 Common Lisp 中,序列是零索引的,所以序列的最后一个索引比它的长度小一。
(defun endingwith (x liste)
(cond
((null liste) '())
((equal (char (string (car liste))
(- (length (string (car liste))) 1))
(char (string x) 0))
(rplacd liste (endingwith x (cdr liste))))
(t
(endingwith x (cdr liste)))))
在 Common Lisp 中调试此类程序的一种方法是进入 REPL 并进行实验。当您使用一个函数并将您发送到调试器时,请在该函数中查找可能有问题的行。
在发布的代码中,(char (string (length (car liste))) 0) 是第一个可能的候选者。在 REPL 中尝试(car liste),看看它是否按预期计算为'HAVE。如果出现这种情况,请尝试(length (car liste))。这会将您再次发送到调试器,并显示类型错误和类似
的消息
LENGTH: HAVE is not a SEQUENCE.
这表明您需要像在原始函数定义的下一行使用(string x)一样使用(string (car liste))。所以,在 REPL 上试试(length (string (car liste)))。现在您应该看到预期值 4,但很明显原始代码行有点混乱,因为char 希望第一个参数是字符串,而第二个参数是索引。所以在 REPL (char (string (car liste)) (length (string (car liste)))) 再试一次。这再次使我们进入调试器并显示如下消息:
CHAR: index 4 should be less than the length of the string.
但该消息提醒我们,在 Common Lisp 中序列是零索引的,长度为 4 的字符串的最后一个索引是 3。所以,再一次在 REPL:(char (string (car liste)) (- (length (string (car liste))) 1))。现在我们成功了,REPL 返回了预期的#\E。在 REPL 解决了这个有问题的行之后,我们现在可以替换原始函数定义中的行,看看它是否有效。确实如此。