我是lisp的新手,试图理解lisp是如何工作的,而且我不知道如何使用大型函数中的局部变量。 在这里,我有一个小的删除,我发送一个数字到一个函数,如果它可以被3,5和7整除,我必须返回一个列表(by3by5by7),如果只有7,返回(by7)等等... 。 这是我的代码:
(defun checknum(n)
let* (resultt '() ) (
if(not(and(plusp n ) (integerp n))) (cons nil resultt) (progn
(if (zerop (mod n 7)) (cons 'by7 resultt) (cons nil resultt))
(if (zerop (mod n 5)) (cons 'by5 resultt) (cons nil resultt))
(if (zerop (mod n 3)) (cons 'by3 resultt) (cons nil resultt) )) ))
但如果我发送21为ex,我只会得到nil,而不是(by3by7)我猜本地变量不会受到我的if语句的影响而且我不知道该怎么做...
答案 0 :(得分:2)
(cons x y)
创建一个新的cons单元并处理结果。要更改变量的值,您需要使用setq
,setf
,push
等,例如:
(defun checknum (n)
(let ((resultt nil))
(when (and (plusp n) (integerp n))
(when (zerop (mod n 7)) (push 'by7 resultt))
(when (zerop (mod n 5)) (push 'by5 resultt))
(when (zerop (mod n 3)) (push 'by3 resultt)))
resultt))
或者更优雅地使用内部函数来分解重复:
(defun checknum (n)
(when (and (plusp n) (integerp n))
(labels ((sub (d nsym res)
(if (zerop (mod n d))
(cons nsym res)
res)))
(sub 7 'by7
(sub 5 'by5
(sub 3 'by3 nil)))))
测试:
CL-USER> (checknum 12)
(BY3)
CL-USER> (checknum 15)
(BY3 BY5)
CL-USER> (checknum 105)
(BY3 BY5 BY7)
CL-USER> (checknum 21)
(BY3 BY7)
答案 1 :(得分:0)
大多数lisp表单/函数都不会修改它们的参数。那些做的将被明确记录为这样做。例如,请参阅adjoin和pushnew,或删除和删除。
为了试图了解lisp如何工作',以各种不同的方式编写相同的功能对我有很大的帮助,所以你可能想要考虑如何编写你的函数而不修改变量,以及为什么以及何时想要/不想使用破坏性修改。
如下所示会产生两次通过,如果需要检查大量数字,则会太慢,但不会破坏性地修改任何数据。
(defun checknum (n)
(remove nil
(mapcar #'(lambda (m sym)
(when (zerop (mod n m)) sym))
'(7 5 3)
'(by7 by5 by3))))
上述方法可以写成不需要两遍等等。