SBCL 64位,1.1.7
如果我想创建一个包并使用package :CL中的一些符号,我将创建一个如下所示的包:
(defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq))但是,在这个包中,如果我定义了一个带有可选参数的函数,并在没有提供可选参数的情况下调用它,我总是会得到一个错误:
(defun test (&optional a))
(test)
invalid number of arguments: 0
[Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
Restarts:
0: [RETRY] Retry SLIME interactive evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 10: #<CLOSURE (COMMON-LISP:LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {100490B95B}>>
3: [ABORT] Exit debugger, returning to top level.定义一个宏会得到相同的错误,但包含更多信息:
(defmacro test (&rest body))
(test)
error while parsing arguments to DEFMACRO TEST:
invalid number of elements in
()
to satisfy lambda list
(&REST BODY):
exactly 2 expected, but 0 found
[Condition of type SB-KERNEL::ARG-COUNT-ERROR]我想可能是因为缺少CL中的一些符号,那么如何解决这个问题呢?谢谢。
发布于 2013-05-30 21:40:21
我相信这将会对这个问题有所帮助。)
CL-USER> (defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq))
#<PACKAGE "FOO">
CL-USER> (in-package :foo)
#<COMMON-LISP:PACKAGE "FOO">
FOO> (defun bar (&optional baz))
; in: DEFUN BAR
; (SB-INT:NAMED-LAMBDA FOO::BAR
; (FOO::&OPTIONAL FOO::BAZ)
; (BLOCK FOO::BAR))
;
; caught COMMON-LISP:STYLE-WARNING:
; suspicious variable in lambda list: &OPTIONAL.
;
; caught COMMON-LISP:STYLE-WARNING:
; suspicious variable in lambda list: &OPTIONAL.
;
; caught COMMON-LISP:STYLE-WARNING:
; The variable &OPTIONAL is defined but never used.
;
; caught COMMON-LISP:STYLE-WARNING:
; The variable BAZ is defined but never used.
;
; compilation unit finished
; caught 4 STYLE-WARNING conditions
BAR
FOO> (in-package :cl)
#<PACKAGE "COMMON-LISP">
CL> (defpackage :foo
(:import-from :cl
:defun :defmacro :in-package :&optional
:null :car :cdr :cons :if
:eq))
Select a symbol to be made accessible in package FOO:
1. COMMON-LISP:&OPTIONAL
2. FOO::&OPTIONAL
Enter an integer (between 1 and 2): 1
#<PACKAGE "FOO">
CL> (in-package :foo)
#<COMMON-LISP:PACKAGE "FOO">
FOO> (defun bar (&optional baz))
; in: DEFUN BAR
; (SB-INT:NAMED-LAMBDA FOO::BAR
; (&OPTIONAL FOO::BAZ)
; (BLOCK FOO::BAR))
;
; caught COMMON-LISP:STYLE-WARNING:
; The variable BAZ is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
COMMON-LISP:STYLE-WARNING: redefining FOO::BAR in DEFUN
BAR
FOO> &optional、&rest等和其他符号一样,你也需要导入这些符号。但是,这可能不是从cl包导入的最佳方式……除非你确定这就是你所需要的。以防万一:您可以逐个符号地:use整个包,而不是:import-from。
发布于 2013-05-30 22:38:22
有趣的是,这可能指出了与SBCL和大多数其他实现的模糊区别。
如果我们在SBCL中创建一个新包,默认情况下该包不使用任何其他包。
因此,这导致了与GNU CLISP的这种时髦的区别:
&optional是所谓的lambda list关键字。
这是GNU CLISP:
[1]> (defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq))
#<PACKAGE FOO>
[2]> (in-package "FOO")
#<PACKAGE FOO>
FOO[3]> (defun test (&optional a))
TEST
FOO[4]> (test)
NIL它可以在CLISP (和大多数其他CL实现)中工作,因为它默认使用"CL“包。SBCL不使用CL包。如果不指定要使用的包,SBCL将使用none。大多数其他实现都会创建一个新的包,其中包含一组默认的要继承的有用包。SBCL开发人员认为这特别聪明,但暴露了不兼容性-我认为这根本不是那么聪明。该标准允许对DEFPACKAGE进行SBCL解释,但由于知道其他实现不会这样做,所以将其更改为SBCL解释。
在GNU CLISP (和大多数其他CL实现)中,import语句没有作用,因为包使用了所有的包"CL“。
SBCL:
* (defpackage "BAR")
#<PACKAGE "BAR">
* (package-use-list "BAR")
NIL与CLISP进行比较:
[1]> (defpackage "BAR")
#<PACKAGE BAR>
[2]> (package-use-list "BAR")
(#<PACKAGE COMMON-LISP>)因此,您需要将SBCL中的lambda list关键字导入到您的包中。
这也意味着你需要像这样写你的包声明:
(defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq
:&optional)
(:use))上面添加了&optional lambda list关键字。您可能还想添加其他lambda列表关键字。
它还明确指定不使用任何包。
发布于 2013-05-30 22:03:42
如果您在包FOO (cl:symbol-package '&optional)中尝试执行以下命令,则可以看到使用的是哪个包。Common Lisp期望在lambda列表中使用cl:&optional,但您使用的是foo::&optional,因为它是一个没有语义的符号,它只是一个参数,就像其他参数一样。
一种方法是将:&optional :&rest添加到从CL封装导入的符号列表中,另一种方法是批量导入,同时隐藏一些要重新定义的符号。
https://stackoverflow.com/questions/16837360
复制相似问题