4

でそれを行う方法がわかりませんsb-ext:muffle-conditions。私はこのようなことをしたい:

(declaim #+sbcl(sb-ext:muffle-conditions sb-kernel:redefinition-warning))

もちろん、再定義の代わりに「未定義の変数」警告をこもらせたい場合を除きます。

誰かがこれがどのパラメータであるかを知っているか、ドキュメント/さまざまなオプションへのリンクを持っている場合は、sb-ext:muffle-conditions共有してください:)ありがとう

4

1 に答える 1

4

この種の警告を具体的に、少なくともクラス名で消すことができるかどうかはわかりません。をトレースwarnすることで、SBCL が何をしているかをある程度把握できます。たとえば、再定義の場合に何が起こるか見てみましょう:

* (trace warn)

(WARN)
* (defun foo () nil)

FOO
* (defun foo () nil)
  0: (WARN SB-KERNEL:REDEFINITION-WITH-DEFUN :NAME FOO :NEW-FUNCTION
           #<FUNCTION FOO {10041FA989}> :NEW-LOCATION
           #S(SB-C:DEFINITION-SOURCE-LOCATION
              :NAMESTRING NIL
              :TOPLEVEL-FORM-NUMBER NIL
              :PLIST NIL))
STYLE-WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
  0: WARN returned NIL
FOO

warnsb-kernel:redefinition-with-defunは、クラス指定子としてクラスと引数を使用して呼び出されるため、通知される警告には、ある程度特定のクラス タイプがあります。特定のクラス タイプに基づいて消音できると、消音が容易になります。

ここで、未定義の変数の場合に何が起こるか見てみましょう:

* (defun foo2 () x)
  0: (WARN "undefined ~(~A~): ~S" :VARIABLE X)

; in: DEFUN FOO2
;     (BLOCK FOO2 X)
; 
; caught WARNING:
;   undefined variable: X
  0: WARN returned NIL
; 
; compilation unit finished
;   Undefined variable:
;     X
;   caught 1 WARNING condition
FOO2

warnフォーマット文字列といくつかの引数を指定して呼び出されているため、通知される警告は単なるsimple-warning. さて、それをこもらせるために何かをすることはできますが、それはもう少し複雑です.

SBCL マニュアルのセクション3.1.1 Controlling Verbosityによると、再起動sb-ext:muffle-conditionsを使用しているだけmuffle-warningです。未定義変数の警告はただの であり、おそらくすべてsimple-warningのを消したいわけではないため、少しこっそりと、ハンドラー バインドで指定されたハンドラーを使用して状態を検査する必要があります。呼び出される引数を見てきたので、キャッチするものを非常に具体的にすることができます。これらの警告は、次のように認識できます。 simple-warningwarnundefined-variable-warning-p

(defun undefined-variable-warning-p (w)
  (let ((control (simple-condition-format-control w))
        (arguments (simple-condition-format-arguments w)))
    (and (= 2 (length arguments))
         (eq :variable (first arguments))
         (string= control "undefined ~(~A~): ~S"))))

これで、コンパイル フォームを適切な .xml でラップできますhandler-bind。たとえば(compile nil (lambda () x))、ハンドラーがある場合とない場合を見てみましょう。

CL-USER> (compile nil '(lambda () x))
; 
; caught WARNING:
;   undefined variable: X
; 
; compilation unit finished
;   Undefined variable:
;     X
;   caught 1 WARNING condition
#<FUNCTION (LAMBDA ()) {1003AA4F89}>
T
T

CL-USER> (handler-bind
             ((simple-warning 
               #'(lambda (w) 
                   (when (undefined-variable-warning-p w)
                     (invoke-restart 'muffle-warning)))))
           (compile nil '(lambda () x)))
#<FUNCTION (LAMBDA ()) {1003B737E9}>
NIL
NIL

関数をコンパイルし、未定義変数の警告をミュートすることに成功しました。ただし、これで s を単純にラップすることはできないことに注意してくださいdefun。例えば、

CL-USER> (handler-bind
             ((simple-warning 
               #'(lambda (w) 
                   (when (undefined-variable-warning-p w)
                     (invoke-restart 'muffle-warning)))))
           (defun some-function () x))

; in: DEFUN SOME-FUNCTION
;     (DEFUN SOME-FUNCTION () X)
; --> PROGN EVAL-WHEN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA FUNCTION 
; ==>
;   (BLOCK SOME-FUNCTION X)
; 
; caught WARNING:
;   undefined variable: X
; 
; compilation unit finished
;   Undefined variable:
;     X
;   caught 1 WARNING condition
SOME-FUNCTION

evalただし、同じ場合defun(ただし、そうすべきだと言っているわけではありません)、警告はこもっています。

CL-USER> (handler-bind
             ((simple-warning 
               #'(lambda (w) 
                   (when (undefined-variable-warning-p w)
                     (invoke-restart 'muffle-warning)))))
           (eval '(defun some-other-function () x)))
SOME-OTHER-FUNCTION

これがなぜなのか正確にはわかりませんが、誰かがコメントで詳しく説明できることを願っています. これは、REPL でフォームをコンパイルする SBCL が原因であると思われます。つまり、フォーム全体が実行される前に本体がコンパイルdefunれるため、ハンドラーが配置される前にコンパイルが行われます。

于 2013-08-10T15:33:34.307 に答える