Common Lisp:错误 "CDR LST should be a lambda expression"

Common Lisp: error "CDR LST should be a lambda expression"

我正在做一个接受一个列表和两个原子的程序,如果 atom-1 出现在列表中,则将 atom-1 替换为 atom-2。
我正在使用 Ubuntu 系统

在文本编辑器中进行编程

下面是我的代码:

#! /usr/bin/clisp

(defun my-replace (lst x y)
  (cond
    ((eq lst nil) nil)
    ((eq (cdr lst) nil) nil)
    ((eq (car lst) x) (setq (car lst) y))
    ( t (my-replace ((cdr lst) x y)))))

当我尝试执行此操作时,Clisp 显示此错误:

*** - SYSTEM::%EXPAND-FORM: (CDR LST) should be a lambda expression

我是 Lisp 初学者。
请告诉我如何解决这个错误。

编辑: 这个答案指出了代码片段中的另一个明显错误。标题中的错误是因为 (cdr lst) x y 周围的额外 parens,使其成为 ((cdr lst) x y),只有当 (cdr lst) 是 lambda 表达式时才有意义,并且可以调用。


通常情况下,如果要将某物绑定到一个值,则使用 setsetqset 的一个特殊版本,当第一个参数是一个 qutoed 值时,所以不是写 (set 'horse 123),而是写 (setq horse 123).

但是,您不想将符号绑定到值,而是希望将列表的元素变成值。这就是你要使用setf的时候。

(let ((lst (list 1 2 3)))
  (setf (car lst) 4)
  (princ lst)) ;; (4 2 3)

有关详细信息,请参阅 this 出色的答案。

首先你应该改进格式和缩进:

(defun my-replace (lst x y)
  (cond
   ((eq lst nil) nil)
   ((eq (cdr lst) nil) nil)
   ((eq (car lst) x) (setq (car lst) y))
   (t (my-replace ((cdr lst) x y)))))

我们来看代码:

(defun my-replace (lst x y)
; in Common Lisp you can write LIST instead of LST
; what are x and y? The naming is not very speaking.

  (cond
   ((eq lst nil) nil)

   ((eq (cdr lst) nil) nil)   ; why this clause?

   ((eq (car lst) x) (setq (car lst) y))
   ; instead of SETQ use SETF

   (t (my-replace ((cdr lst) x y)))))
                  ; here is a function call? why the extra parentheses

我会首先关注一个非破坏性的版本。您尝试编写一个破坏性修改列表的版本。不。创建一个完成替换的新列表。

如果你想写一个破坏性的版本,你可以这样做,但首先要把基础做好。