我对LISP很新,我正在努力研究课堂上的cond声明。目前,我正在尝试检查传递的值是否为列表,如果是,请将字母d附加到列表中。
这是我的代码:
(defun test(L)
(listp L)
(cond ((listp L) (append L (list 'd)))
)
(write L)
)
(test (list 'a 'b 'c))
我得到的输出是:
(A B C)
(A B C)
如果我将测试更改为:(test (car(list 'a 'b 'c)))
我得到的新输出是:
A
A
我想知道的两件事是
1。)如果第一个测试通过列表,为什么D不会附加到列表中?
2。)为什么要打印两次?我正在使用LISP Works,所以我认为它实际上是它总是输出最终值的东西。
答案 0 :(得分:3)
1。)同样的原因str + "d"
不会在Java或Python中改变str
。它会创建一个您不使用的新列表!
>>> str + "d"
'abcd'
>>> str
'abc'
疯狂的相似不是吗?
2.)在CL中,return
是最后一次计算的表达式。 REPL将每个顶级表达式结果打印到终端。 Python也是这样做的:
>>> def test():
... x = 2 + 3
... print x
... return x
...
>>> test()
5
5
如何改变参数列表。简单的答案是你需要改变最后一对参数:
(defun test (l)
(assert (consp 1) (l) "l needs to be a non nil list. Got: ~a" l)
(nconc l (list 'd)
(write l)))
(defparameter *test1* (list 1 2 3))
(defparameter *test1-copy* *test1*)
(test *test1*) ; ==> (1 2 3 d) (and prints (1 2 3 d))
*test1* ; ==> (1 2 3 d)
*test1-copy* ; ==> (1 2 3 d)
(eq *test1* *test1-copy*) ; ==> t
(test '())
** error l needs to be a non nil list. Got: NIL
(nconc l x)
执行(setf (cdr (last l)) x)
如果你需要改变绑定,那么你需要制作一个宏:
(defmacro testm (var)
(assert (symbolp var) (var) "List needs to be a variable binding. Got: ~a" var)
`(progn
(when (listp ,var)
(setf ,var (append ,var (list 'd)))
(write ,var))))
(macroexpand '(testm *test2*))
; ==> (progn
; (when (consp *test2*)
; (setf *test2* (append *test2* (list 'd))))
; (write *test2*))
(defparameter *test2* (list 1 2 3))
(defparameter *test2-copy* *test2*)
(testm *test2*) ; ==> (1 2 3 d) (and prints (1 2 3 d))
*test2* ; ==> (1 2 3 d)
*test2-copy* ; ==> (1 2 3)
(eq *test2* *test2-copy*) ; ==> nil
(defparameter *x* nil)
(testm *x*) ; ==> (d) (and prints (d))
*x* ; ==> (d)
(testm '(1))
** error List needs to be a variable binding. Got: '(1)
(defun test (list)
(if (consp list)
(append list '(d))
list))
(write (test '(1 2 3)))
; ==> (1 2 3 d) (and prints (1 2 3 d))
(defparameter *test3* '(1 2 3))
(setf *test3* (test *test3*))
*test3* ; ==> (1 2 3 d)