在推杆中推错误

时间:2013-12-20 06:52:23

标签: 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)
  )

为什么我会Error: Illegal function object: (PUSH ELEM Z). [condition type: TYPE-ERROR]? 这是什么意思?

2 个答案:

答案 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表单。除非您在显示的代码之外创建了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)))

现在letzcontorcounter建立了本地绑定。

上一个错误:e未在显示的代码中绑定。我不知道你想在这里做什么,但我认为你只是想在你努力创造它之后返回z。由于您将lpush循环到zzl的相应值相比具有相反的顺序。如果你想拥有相同的订单,那么成语就是在最后使用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)))
)