2013-12-20 45 views
1
(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]? 这是什么意思?dolist推送错误

+0

'(push elem z)'之前有一个额外的圆括号。 – Barmar

+2

我不是在你之前的问题中告诉你,你不应该在函数中放置'defparameter'? – Barmar

+0

[LISP“错误非法函数对象...”的可能重复](http://stackoverflow.com/questions/13213605/lisp-error-illegal-function-object) –

回答

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 (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 a 全局特殊变量。在您至少调用一次此功能后,您的整个程序中的任何地方都可以使用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表格。除非您在示出的代码之外创建了contorcounter的绑定,否则此代码具有未定义的行为(“可能发生任何事情”)。 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建立了zcontorcounter本地绑定。

最后一个错误:e没有绑定在显示的代码中。我不知道你想在这里做什么,但我认为你只是想在你付出这样的痛苦创造它之后返回z。由于您将lpush循环到z,zl的对应值相比具有相反的顺序。这个成语,如果你想要有相同的顺序,最后使用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的原因。我想这是纠正这是你的下一个努力。

+0

优秀的答案!如果我可以不止一次地使用它,我会的。 –

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))) 
)