(defun remov(l)
(defparameter z ())
(setq contor 0)
(setq counter 0)
(dolist (elem l)
(if
(or (< (expt 2 contor) counter) (> (expt 2 contor) counter))
((push elem z) (setq contor (+ 1 contor))) (setq counter (+ 1 counter)))
)
(print e)
)
为什么我会Error: Illegal function object: (PUSH ELEM Z).
[condition type: TYPE-ERROR]
?
这是什么意思?
答案 0 :(得分:5)
请了解Lisp中如何使用缩进和空格,以及换行有用的地方以及不用的地方。
(defun remov (l)
(defparameter z ())
(setq contor 0)
(setq counter 0)
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
((push elem z) (setq contor (+ 1 contor)))
(setq counter (+ 1 counter))))
(print e))
直接问题:if
接受三个参数,评估第一个参数,然后计算并返回第二个或第三个参数。第二种形式是:
((push elem z) (setq contor (+ 1 contor)))
求值表单的第一个元素是运算符,它是函数或特殊运算符的名称,或lambda表达式。 lambda表达式是(lambda (x) ...)
之类的形式。在这里,(push elem z)
不符合该描述。这就是你得到的错误。
你的意图似乎是一个接一个地做两件事。这通常以progn
形式完成。
(progn
(push elem z)
(setq contor (+ 1 contor)))
这会产生:
(defun remov (l)
(defparameter z ())
(setq contor 0)
(setq counter 0)
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
(progn
(push elem z)
(setq contor (+ 1 contor)))
(setq counter (+ 1 counter))))
(print e))
现在,defparameter
。这使z
成为全局特殊变量。在您至少调用此函数一次后,z
将在整个程序中的任何位置特殊。那不是你想要的。看来你只想建立一个新的本地绑定。请使用let
。
(defun remov (l)
(let ((z ()))
(setq contor 0)
(setq counter 0)
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
(progn
(push elem z)
(setq contor (+ 1 contor)))
(setq counter (+ 1 counter))))
(print e)))
然后,您有两个setq
表单。除非您在显示的代码之外创建了contor
和counter
的绑定,否则此代码具有未定义的行为(“可能发生任何事情”)。 Setq
未建立新绑定。您似乎只想建立新的本地绑定,就像使用z
一样。使用let
表单。
(defun remov (l)
(let ((z ())
(contor 0)
(counter 0))
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
(progn
(push elem z)
(setq contor (+ 1 contor)))
(setq counter (+ 1 counter))))
(print e)))
现在let
为z
,contor
和counter
建立了本地绑定。
上一个错误:e
未在显示的代码中绑定。我不知道你想在这里做什么,但我认为你只是想在你努力创造它之后返回z
。由于您将l
和push
循环到z
,z
与l
的相应值相比具有相反的顺序。如果你想拥有相同的订单,那么成语就是在最后使用nreverse
。函数返回最后一个表单的值。
(defun remov (l)
(let ((z ())
(contor 0)
(counter 0))
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
(progn
(push elem z)
(setq contor (+ 1 contor)))
(setq counter (+ 1 counter))))
(nreverse z)))
现在,让我们简化一下。要将setq
变量设置为1+
,请使用宏incf
。 (Incf foo)
扩展为(setq foo (1+ foo))
。
(defun remov (l)
(let ((z ())
(contor 0)
(counter 0))
(dolist (elem l)
(if (or (< (expt 2 contor) counter)
(> (expt 2 contor) counter))
(progn
(push elem z)
(incf contor))
(incf counter)))
(nreverse z)))
如果a
或>
的整数<
比/=
或(defun remov (l)
(let ((z ())
(contor 0)
(counter 0))
(dolist (elem l)
(if (/= (expt 2 contor) counter)
(progn
(push elem z)
(incf contor))
(incf counter)))
(nreverse z)))
更大,则为(defun remove-when-foo (list)
(let ((result ())
(contor 0)
(counter 0))
(dolist (element list)
(if (/= (expt 2 contor) counter)
(progn
(push element result)
(incf contor))
(incf counter)))
(nreverse z)))
。
if
我倾向于避免使用名称缩写。
remove-when-foo
我对这个逻辑感到有点惊讶,因为{{1}}形式的条件在这个循环中总是正确的。这就是我将它命名为{{1}}的原因。我想纠正这个是你下一步的努力。
答案 1 :(得分:3)
如果要将多个表达式作为块执行,则必须使用progn
,不能将它们包装在列表中。列表的第一个元素应该是要调用的函数,(push elem z)
不是有效的函数。
(if
(or (< (expt 2 contor) counter) (> (expt 2 contor) counter))
(progn
(push elem z)
(setq contor (+ 1 contor)))
(setq counter (+ 1 counter)))
)