5

SBCL 64 ビット、1.1.7

パッケージを作成し、パッケージ :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 からいくつかのシンボルが不足しているためだと思いますが、この問題を解決するにはどうすればよいですか? ありがとう。

4

3 に答える 3

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> 

&optionalなど&restは他のシンボルと同様に単なるシンボルであるため、それらもインポートする必要があります。しかし、これはパッケージからインポートする最良の方法ではないかもしれませんcl...それが必要なものであると確信していない限り. 念のため:シンボル:useごとではなく、パッケージ全体を対象にすることもできます。:import-from

于 2013-05-30T13:40:21.213 に答える
6

興味深いことに、これは SBCL や他のほとんどの実装とのあいまいな違いを示している可能性があります。

SBCL で新しいパッケージを作成すると、そのパッケージはデフォルトで他のパッケージを使用しません。

したがって、これは、たとえば GNU CLISP とのこのファンキーな違いにつながります。

&optionalいわゆるラムダ リスト キーワードです。

これは 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

デフォルトで「CL」パッケージを使用するため、CLISP (および他のほとんどの CL 実装) で動作します。SBCL はパッケージを使用しません。CL使用するパッケージを指定しない場合、SBCL何も使用しません。他のほとんどの実装では、継承する有用なパッケージのデフォルト セットを含む新しいパッケージが作成されます。SBCL の開発者は、これは特に巧妙であると考えていましたが、非互換性を露呈しています。これはまったく巧妙ではないと思います。標準では の SBCL 解釈が許可DEFPACKAGEされていますが、他の実装ではそうではないことがわかっているため、これに変更されました。

GNU CLISP (および他のほとんどの CL 実装) では、パッケージがすべてのパッケージ "CL" をとにかく使用するため、import ステートメントは効果がありません。

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 のラムダ リスト キーワードをパッケージにインポートする必要があります。

また、次のようにパッケージ宣言を記述する必要があることも意味します。

(defpackage :foo
  (:import-from :cl 
   :defun :defmacro :in-package
   :null :car :cdr :cons :if
   :eq
   :&optional)
  (:use))

上記は、&optional ラムダ リスト キーワードを追加します。他のラムダ リスト キーワードも追加することをお勧めします。

また、パッケージを使用しないことも明示的に指定します。

于 2013-05-30T14:38:22.037 に答える
4

パッケージ FOO(cl:symbol-package '&optional)で以下を試すと、どのパッケージが使用されているかがわかります。Common Lisp は がラムダ リストで使用されることを想定してcl:&optionalいますが、あなたが使用foo::&optionalしているのは and であり、これは意味的な意味を持たないシンボルであるため、他のパラメーターと同様に単なるパラメーターです。

:&optional :&rest1 つのオプションは、CL パッケージからインポートするシンボルのリストに追加することです。別のオプションは、再定義するいくつかのシンボルを隠しながら、それを卸売りでインポートすることです。

于 2013-05-30T14:03:41.537 に答える