1

当我从 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)).

4

2 回答 2

3

有问题的声明

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

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

错误:列表不是向量

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

FIRST然后该函数使用对and的调用LAST,这对向量不起作用,但对列表起作用。

运行具有更高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类型没有参数

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

于 2014-01-05T03:32:25.643 回答
2

declarerowlist是一个vector(但对待它是一个list- 使用lastand first)。这意味着编译器假定您传递给它的对象是 a vector,因此,当您传递给它 a 时list,您会得到未定义的行为

关于 Lisp 中的声明,最重要的一点是:不要编译器撒谎。即,如果您违反您的声明(就像您刚才所做的那样),您将被烧毁。

(此外,您不需要eval nil,也不需要 ,let*因为您只使用它绑定一次的变量)。

于 2014-01-05T00:32:17.077 回答