我正在寻求提高我收到的编译器警告的质量和数量 - 在Common Lisp中是否有一种方法可以在声明的类型和实例上包含类型谓词 - 特定于实现的答案很好,我很感兴趣看看它是如何完成的,如果有人这样做的话.
在CCL中编译以下内容:
(defun non-list (o)
(not (listp o)))
(deftype non-list ()
'(satisfies non-list))
(defun example (a)
(list a))
(declaim (ftype (function (non-list) list) example))
(defun hmm ()
(declare (optimize (debug 3) (safety 3)))
(let ((a '(a b c))
(b '(d e f)))
(declare (type list a))
(example '(g h i))
(example a)
(example b)))
Run Code Online (Sandbox Code Playgroud)
我会在第一次调用时收到编译器警告example- 提供可以检查的实例satisfies.这很好,使用调试设置我会得到一个好的运行时错误.我想知道的是,如果我能写出如下内容:
(defun non-list-typep (type)
(not (subtypep type 'list)))
Run Code Online (Sandbox Code Playgroud)
并以某种方式集成它,以便至少第二次调用 - (example a)将在编译时警告,因为它的声明类型list将使谓词失败non-list-typep
干杯!
有点背景:
有两种不同的东西:标准语言Common Lisp和广泛不同的语言实现和扩展Common Lisp.
Common Lisp作为一种语言在编译时不需要类型警告/错误.实现可以主要忽略类型声明.当编译器不忽略类型声明以及如何使用它们来静态检查类型时,该语言也没有真正描述应该做什么.
当涉及静态声明的类型时,实际Common Lisp编译器属于以下组:
主要忽略它们.例如,Symbolics Lisp Machine的编译器属于该组.
使用声明的类型主要用于优化目的.我会说CCL属于这个群体.我认为它不会对类型信息进行太多的类型推断或传播.我猜这也是编译器比SBCL更快的原因 - 它做得更少.
使用声明的类型主要用于优化目的,但可以进行类型推断并可以提供类型信息(用于优化).例如,LispWorks属于这一群体.
使用声明的类型进行优化,进行类型推断,可以提供类型信息,并将类型声明视为编译时类型断言.CMUCL和SBCL编译器是该组的主要成员.
因此,对于类型2的实现,如果希望编译器识别它,则最好需要声明所有内容.请注意,Common Lisp提供THE并LOCALLY编写声明.
如果你想将类型声明作为静态类型断言并让编译器检查它们,你最好使用像SBCL这样的编译器.
关于类型声明方法的一些背景知识可以在SBCL手册:编译时类型和类型错误的处理中找到.更多背景:CMU Common Lisp的Python编译器.请注意,CMU Common Lisp(以及后来的SBCL)的编译器称为Python - 它与编程语言Python无关.在Python(1991)语言出现之前,编译器已经有了它的名字(20世纪80年代早期).