我正在做一个接受一个列表和两个原子的程序,如果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的初学者 请告诉我如何解决这个错误。
答案 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表达式时才有意义,并且可以被调用。
通常,如果想要将某些内容绑定到值,则使用set
。 setq
是set
的特殊版本,当第一个参数是qutoed值时,您可以编写(set 'horse 123)
而不是写(setq horse 123)
。
但是,您不希望将符号绑定到值,而是希望将列表元素转换为值。这是您想要使用setf
的时候。
(let ((lst (list 1 2 3)))
(setf (car lst) 4)
(princ lst)) ;; (4 2 3)
有关详细信息,请参阅this出色的答案。