首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于common-lisp中的可选参数的错误

关于common-lisp中的可选参数的错误
EN

Stack Overflow用户
提问于 2013-05-30 21:20:58
回答 3查看 936关注 0票数 5

SBCL 64位,1.1.7

如果我想创建一个包并使用package :CL中的一些符号,我将创建一个如下所示的包:

代码语言:javascript
复制
(defpackage :foo
  (:import-from :cl 
                :defun :defmacro :in-package
                :null :car :cdr :cons :if
                :eq))

但是,在这个包中,如果我定义了一个带有可选参数的函数,并在没有提供可选参数的情况下调用它,我总是会得到一个错误:

代码语言:javascript
复制
(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.

定义一个宏会得到相同的错误,但包含更多信息:

代码语言:javascript
复制
(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中的一些符号,那么如何解决这个问题呢?谢谢。

EN

回答 3

Stack Overflow用户

发布于 2013-05-30 21:40:21

我相信这将会对这个问题有所帮助。)

代码语言:javascript
复制
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

票数 7
EN

Stack Overflow用户

发布于 2013-05-30 22:38:22

有趣的是,这可能指出了与SBCL和大多数其他实现的模糊区别。

如果我们在SBCL中创建一个新包,默认情况下该包不使用任何其他包。

因此,这导致了与GNU CLISP的这种时髦的区别:

&optional是所谓的lambda list关键字。

这是GNU CLISP:

代码语言:javascript
复制
[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:

代码语言:javascript
复制
* (defpackage "BAR")

#<PACKAGE "BAR">

* (package-use-list "BAR")

NIL

与CLISP进行比较:

代码语言:javascript
复制
[1]> (defpackage "BAR")
#<PACKAGE BAR>
[2]> (package-use-list "BAR")
(#<PACKAGE COMMON-LISP>)

因此,您需要将SBCL中的lambda list关键字导入到您的包中。

这也意味着你需要像这样写你的包声明:

代码语言:javascript
复制
(defpackage :foo
  (:import-from :cl 
   :defun :defmacro :in-package
   :null :car :cdr :cons :if
   :eq
   :&optional)
  (:use))

上面添加了&optional lambda list关键字。您可能还想添加其他lambda列表关键字。

它还明确指定不使用任何包。

票数 6
EN

Stack Overflow用户

发布于 2013-05-30 22:03:42

如果您在包FOO (cl:symbol-package '&optional)中尝试执行以下命令,则可以看到使用的是哪个包。Common Lisp期望在lambda列表中使用cl:&optional,但您使用的是foo::&optional,因为它是一个没有语义的符号,它只是一个参数,就像其他参数一样。

一种方法是将:&optional :&rest添加到从CL封装导入的符号列表中,另一种方法是批量导入,同时隐藏一些要重新定义的符号。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16837360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档