Common lisp 为什么这个函数会使LispWorks崩溃?
当我从LispWorks中的侦听器运行此函数时,它要么使侦听器崩溃,要么给出异常和汇编语言数据。有谁能告诉我它有什么问题吗Common lisp 为什么这个函数会使LispWorks崩溃?,common-lisp,lispworks,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 (=
(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 2 1))
您声明行列表
是一个向量(但它是一个列表
——使用最后一个和第一个)。
这意味着编译器假定您传递给它的对象是一个向量
,因此,当您传递给它一个列表
时,您会得到未定义的行为
关于Lisp中的声明,需要知道的最重要的事情是:不要对编译器撒谎。
也就是说,如果你违反了你的声明(就像你刚才做的那样),你会被烧死
(此外,您不需要eval
nil
,也不需要let*
,因为您只使用了它绑定的变量一次)。您声明行列表
是向量
(但使用最后一个和第一个)。
这意味着编译器假定您传递给它的对象是一个向量
,因此,当您传递给它一个列表
时,您会得到未定义的行为
关于Lisp中的声明,需要知道的最重要的事情是:不要对编译器撒谎。
也就是说,如果你违反了你的声明(就像你刚才做的那样),你会被烧死
(此外,您不需要eval
nil
,也不需要let*
,因为您只使用了它绑定的变量一次)。有问题的声明
请注意,并非所有常见的Lisp实现都认为(declare((vector number))rowvector)
是有效的声明
改为编写(声明(类型(向量号)行向量))
错误:列表不是向量
您看到的问题是因为您对实现撒谎,并且安全性设置为低。您告诉Lisp参数是一个向量,但您传递了一个列表(它不是向量)
然后,该函数使用对FIRST
和LAST
的调用,这两个函数对向量无效,但对列表有效
以更高的安全性运行代码
值
默认情况下,不要在安全性较低的情况下运行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)
是一个向量
注意:列表
类型没有参数
请注意,Common Lisp中不存在类型(列表编号)
,因此无法定义。类型列表
不能有参数。基于类型cons
也无法定义这样的类型-递归类型不起作用。有问题的声明
请注意,并非所有常见的Lisp实现都认为(declare((vector number))rowvector)
是有效的声明
改为编写(声明(类型(向量号)行向量))
错误:列表不是向量
您看到的问题是因为您对实现撒谎,并且安全性设置为低。您告诉Lisp参数是一个向量,但您传递了一个列表(它不是向量)
然后,该函数使用对FIRST
和LAST
的调用,这两个函数对向量无效,但对列表有效
以更高的安全性运行代码
值
默认情况下,不要在安全性较低的情况下运行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)
是一个向量
注意:列表
类型没有参数
请注意,Common Lisp中不存在类型(列表编号)
,因此无法定义。类型列表
不能有参数。基于类型cons
,也不可能定义这样的类型-递归类型不起作用。它被称为(应翻转块’(1 2 1))。删除declare确实解决了问题,但它不允许我(declare((列表编号)rowlist))。@MarkGreen您能澄清一下您所说的“…它不允许我(declare((列表编号)rowlist))
”是什么意思吗?当我尝试使用该declare代替矢量一时,我得到一个错误——“不知道如何处理声明”。噢,我认为这是一个警告。但这可能是不好的,因为它应该能够对声明做一些事情,它被称为(shouldlipblock'(1-2-1))。删除declare确实解决了问题,但它不允许我(declare((列表编号)rowlist))。@MarkGreen您能澄清一下您所说的“…它不允许我(declare((列表编号)rowlist))
”是什么意思吗?当我尝试使用该declare代替矢量一时,我得到一个错误——“不知道如何处理声明”。噢,我认为这是一个警告。但这大概是不好的,因为它应该能够对声明做些什么。