Common Lisp:错误" CDR LST应该是lambda表达式"

时间:2015-09-23 09:39:38

标签: recursion lisp common-lisp clisp

我正在做一个接受一个列表和两个原子的程序,如果atom-1出现在列表中,则用atom-2替换atom-1。
我正在使用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的初学者 请告诉我如何解决这个错误。

2 个答案:

答案 0 :(得分:8)

首先,您应该改进格式和缩进:

(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

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

如果你想写一个破坏性版本,你可以这样做,但首先要掌握基础知识。

答案 1 :(得分:2)

编辑: 这个答案指出了代码段中的另一个明显错误。标题中的错误是因为(cdr lst) x y周围的额外问题,使其成为((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出色的答案。