Lisp-在函数的多个语句中修改局部变量
Lisp- modifying a local variable inside multiple statements on a function
我是 lisp 的新手,试图了解 lisp 的工作原理,但我不知道如何在大型函数中使用局部变量。
在这里,我有一点兴奋,我将一个数字发送给一个函数,如果它可以被 3、5 和 7 整除,我必须 return 一个 (by3by5by7) 的列表,如果只能被 7,return ( 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) )) ))
但是如果我为 ex 发送 21,我只会得到 nil,而不是 (by3by7) 我猜局部变量不受我的 if 语句的影响,我不知道该怎么做...
(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)
大多数 lisp forms/functions 不修改它们的参数。那些这样做的将被明确记录为这样做。例如,参见 adjoin 和 pushnew,或者 remove 和 delete。
至此 'trying to understand how lisp works',以各种不同的方式编写相同的函数对我帮助很大,因此您可能想考虑如何在完全不修改变量的情况下编写函数,以及为什么以及何时想要/不想使用破坏性修改。
像下面这样的东西会进行两次传递,如果需要检查的数字量很大,速度会太慢,但不会破坏性地修改任何东西。
(defun checknum (n)
(remove nil
(mapcar #'(lambda (m sym)
(when (zerop (mod n m)) sym))
'(7 5 3)
'(by7 by5 by3))))
上面的方法可以写成不需要两遍等
我是 lisp 的新手,试图了解 lisp 的工作原理,但我不知道如何在大型函数中使用局部变量。 在这里,我有一点兴奋,我将一个数字发送给一个函数,如果它可以被 3、5 和 7 整除,我必须 return 一个 (by3by5by7) 的列表,如果只能被 7,return ( 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) )) ))
但是如果我为 ex 发送 21,我只会得到 nil,而不是 (by3by7) 我猜局部变量不受我的 if 语句的影响,我不知道该怎么做...
(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)
大多数 lisp forms/functions 不修改它们的参数。那些这样做的将被明确记录为这样做。例如,参见 adjoin 和 pushnew,或者 remove 和 delete。
至此 'trying to understand how lisp works',以各种不同的方式编写相同的函数对我帮助很大,因此您可能想考虑如何在完全不修改变量的情况下编写函数,以及为什么以及何时想要/不想使用破坏性修改。
像下面这样的东西会进行两次传递,如果需要检查的数字量很大,速度会太慢,但不会破坏性地修改任何东西。
(defun checknum (n)
(remove nil
(mapcar #'(lambda (m sym)
(when (zerop (mod n m)) sym))
'(7 5 3)
'(by7 by5 by3))))
上面的方法可以写成不需要两遍等