为什么这个函数会破坏LispWorks?

时间:2014-01-05 00:02:16

标签: common-lisp lispworks

当我从LispWorks中的侦听器运行此函数时,它会使侦听器崩溃或提供异常和汇编语言数据。谁能告诉我它有什么问题?

(defun should-flip-block (rowlist)
  (declare ((vector number) rowlist))
  (if (= (length rowlist) 0) (eval nil) 
    (let* ((exithigh (= (car (last rowlist)) 2))
           (enterhigh (= (first rowlist) 2)))  
      (and exithigh enterhigh))))

它被称为(should-flip-block '(1 2 1 2 1))

2 个答案:

答案 0 :(得分:3)

有问题的声明

请注意,并非所有Common Lisp实现都会认为(declare ((vector number)) rowvector)是有效的声明。

改为(declare (type (vector number) rowvector))

错误:列表不是矢量

您看到的问题是因为您对实施做出了谎言而safety设置得很低。你告诉Lisp这个参数是一个向量,但是你传递一个列表(它不是一个向量)。

然后该函数使用对FIRSTLAST的调用,这些调用不适用于向量,而是列表。

运行safety值更高的代码

默认情况下,不要以低安全性运行Common Lisp。使用默认安全值2或3。

使用LispWorks 6.1.1:

CL-USER 43 > (proclaim '(optimize (safety 2)))
NIL

现在我重新编译该函数,然后调用它:

CL-USER 44 > (should-flip-block '(1 2 1 2 1))

Error: Variable ROWLIST was declared type (VECTOR NUMBER) but is being
       bound to value (1 2 1 2 1)
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

现在您看到了有用的错误,而不是段违规。

文字向量

#(1 2 1 2 1)是一个向量。

注意:LIST类型没有参数

请注意,Common Lisp中不存在类型(list number),无法定义。类型list不能包含参数。根据类型cons定义这样的类型也是不可能的 - 递归类型不起作用。

答案 1 :(得分:2)

declare rowlist vector list last使用firstvectorlist进行处理。eval 这意味着编译器假设您传递给它的对象是nil,因此,当您传递let*时,您会得到未定义的行为

了解Lisp中声明的最重要的事情是:撒谎到编译器。 即,如果你违反了你的声明(就像你刚才那样),你就会被烧毁。

(此外,您不需要{{1}} {{1}},并且不需要{{1}},因为您使用的是仅绑定一次的变量。