Common Lisp编译Calendrical Calculations库报CC4包错误咨询
报错根因
报错是因为calendar.l开篇直接执行(in-package "CC4"),但代码中没有预先定义名为CC4的包。Common Lisp标准要求in-package传入的包名必须已经存在,SBCL检测到包不存在就会抛出你看到的SIMPLE-PACKAGE-ERROR。
随《Calendrical Calculations》发布的配套Lisp代码是教学用途的脚本,没有做标准Common Lisp库的包定义、系统配置,所以直接编译会触发这个问题。
可用解决方法
方法1:最小修改源文件(一劳永逸,后续加载不用重复操作)
- 打开
c:/Users/card9/lispstick/calendar.l,在所有代码的最顶部(原有(in-package "CC4")行之前)加入如下包定义代码:
(defpackage #:cc4 (:use #:cl) )
- 保存文件后,在REPL依次执行:
(compile-file "c:/Users/card9/lispstick/calendar.l") (load "c:/Users/card9/lispstick/calendar.fasl")
- 调用库函数时,用包名前缀即可,例如
(cc4:gregorian-from-fixed 0)。如果想省略前缀,执行(use-package '#:cc4)后就可以直接输入函数名调用。
方法2:不修改源文件,REPL手动预处理
如果不想改动原始下载的库文件,直接在REPL按顺序执行以下命令即可完成编译加载:
;; 1. 预先创建缺失的CC4包 (defpackage #:cc4 (:use #:cl)) ;; 2. 进入CC4包后编译源文件 (in-package #:cc4) (compile-file "c:/Users/card9/lispstick/calendar.l") ;; 3. 加载编译产物 (load "c:/Users/card9/lispstick/calendar.fasl")
注意:该方法在每次重启REPL后都需要重新执行上述流程。如果需要长期使用,可以把建包、加载的代码写到SBCL的用户初始化文件
C:/Users/card9/.sbclrc中,REPL启动时会自动加载。
补充说明
- Common Lisp领域中,把第三方代码加载到运行环境的标准术语是加载库或加载系统。正规发布的Common Lisp库一般会提供ASDF系统定义,配合Quicklisp包管理器可以用
ql:quickload一键完成下载、编译、加载,不需要手动处理包定义和路径问题。 - 你参考的《Practical Common Lisp》中关于包、构建系统的章节有明确规则:所有
in-package调用前必须先通过defpackage完成对应包的定义,否则编译、加载阶段都会触发错误。
内容的提问来源于stack exchange,提问作者Gerard Ashton
相关产品推荐
相关产品推荐

