Common Lisp:函数类型说明符中*符号在SBCL 2.1.9下的报错问题
问题解答
1. 该写法是否符合Common Lisp标准规范?
不符合ANSI Common Lisp规范。根据规范,FUNCTION类型说明符的参数部分只有两种合法写法:
- 单独使用
*代表接受任意数量、任意类型的参数,示例:(function * int) - 使用明确的参数类型列表,每个位置必须为合法类型说明符,不能单独使用
*指代单个参数的类型
你用到的(function (*) int)属于SBCL历史上的非标准扩展,并非标准语法。
2. 为什么大量开发者在使用该写法?
SBCL 2.1.8及更早版本长期兼容了一个非标准扩展:允许函数类型参数列表中单独出现的*等价于T,即指代任意类型的单个参数。很多长期基于SBCL开发的项目、资深开发者习惯了这个扩展特性,没有特意区分标准语法和SBCL专属扩展,所以才会大量出现该写法。
3. 为什么SBCL 2.1.9会报错?
这是SBCL 2.1.9版本的有意调整,并非你的编译过程出错。该版本收紧了类型说明符的校验规则,默认禁用了上述非标准扩展,目的是更严格地对齐ANSI CL规范,因此会对不符合标准的*用法抛出错误。你看到的测试全部通过是SBCL自身的标准符合性测试,该调整本身就是测试覆盖的预期行为。
4. 不需要逐个修改代码的解决方案
你可以选择以下任意一种方式解决,无需手动修改所有依赖库的代码:
- 方案一:临时降级到SBCL 2.1.8版本,恢复对该扩展语法的兼容
- 方案二:在你的SBCL启动配置文件(通常为
~/.sbclrc)中添加如下代码,在捕获到对应错误时自动跳过校验:
(handler-bind ((simple-error (lambda (e) (let ((msg (simple-condition-format-control e))) (when (and msg (search "* is not permitted as an argument to the FUNCTION type specifier" msg)) (invoke-restart 'continue))))))
- 方案三:在加载所有依赖前先定义一个宏替换规则,自动将所有
(function (*) ...)形式转换为符合标准的(function (t) ...)形式,无需修改源码。
内容的提问来源于stack exchange,提问作者Numbra
相关产品推荐
相关产品推荐

