xie*_*pan 5 sbcl common-lisp optional-arguments ansi-common-lisp
SBCL 64位,1.1.7
如果我想创建一个包并使用包中的一些小符号:CL,我将创建一个像这样的包:
(defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq))
Run Code Online (Sandbox Code Playgroud)
但是,在这个包中,如果我定义一个带有可选参数的函数并在不提供可选参数的情况下调用它,我总会得到一个错误:
(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.
Run Code Online (Sandbox Code Playgroud)
定义宏得到相同的错误,但有更多信息:
(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]
Run Code Online (Sandbox Code Playgroud)
我想也许是因为缺少一些符号:CL,那么如何解决这个问题呢?谢谢.
小智 7
我相信这会对这个问题有所了解;)
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>
Run Code Online (Sandbox Code Playgroud)
&optional,&rest等等.就像任何其他的符号,你需要导入这些了.但是,也许这不是从cl包中导入的最佳方式......除非你确定这是你需要的.以防万一:您可以:use使用整个包而不是:import-from符号.
有趣的是,这可能意味着与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
Run Code Online (Sandbox Code Playgroud)
它工作在CLISP(和大多数其他CL实现),因为它使用默认的"CL"包.SBCL不使用该CL包.如果您未指定要使用的程序包,则SBCL不使用任何程序包.大多数其他实现创建一个新包,其中包含一组默认的有用包继承.SBCL开发人员认为这是特别聪明,但暴露了不兼容性 - 我认为这根本不是那么聪明.该标准允许对SBCL进行解释DEFPACKAGE,但是已经将其更改为已知其他实现不会这样做.
在GNU CLISP(以及大多数其他CL实现)中,import语句没有效果,因为程序包仍然使用所有包"CL".
SBCL:
* (defpackage "BAR")
#<PACKAGE "BAR">
* (package-use-list "BAR")
NIL
Run Code Online (Sandbox Code Playgroud)
与CLISP相比:
[1]> (defpackage "BAR")
#<PACKAGE BAR>
[2]> (package-use-list "BAR")
(#<PACKAGE COMMON-LISP>)
Run Code Online (Sandbox Code Playgroud)
因此,您需要将SBCL中的lambda list关键字导入到包中.
这也意味着你需要像这样编写包声明:
(defpackage :foo
(:import-from :cl
:defun :defmacro :in-package
:null :car :cdr :cons :if
:eq
:&optional)
(:use))
Run Code Online (Sandbox Code Playgroud)
上面添加了&optional lambda list关键字.您可能还想添加其他lambda列表关键字.
它还明确指定不使用任何包.
| 归档时间: |
|
| 查看次数: |
753 次 |
| 最近记录: |