How to drown out an "undefined variable" warning?

I cannot figure out how to do this with sb-ext:muffle-conditions . I want to do something like this:

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

In addition, I want, however, to silence the warning "undefined" instead of overriding.

If anyone knows which parameter this is or has a link to the documentation / various options for sb-ext:muffle-conditions , please share :) Thanks

+4
source share
1 answer

I'm not sure if you can somehow drown out this type of warning, at least by class name. By warn , we can get an idea of ​​what SBCL does. For example, see what happens when overriding:

 * (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 

warn is called with the sb-kernel:redefinition-with-defun class and arguments as the class designation, and therefore the warning that is signaled has a somewhat specific type class. The ability to muffle based on a particular type of class facilitates the muffling process.

Now let's see what happens with the undefined variable:

 * (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 is called with a format string and some arguments, so the warning that is signaled is simple-warning . Now you can still do something to drown it out, but it's a little more complicated.

According to the SBCL 3.1.1 manual section, Monitoring ellipsis , sb-ext:muffle-conditions uses muffle-warning restart. Since the warning of the undefined variable is just simple-warning , and we probably don't want to drown out all simple-warning s, we need to sneak up a bit and check the condition using the handler specified by the handler's handler. Since we saw the arguments with which we call warn , we can be very specific in what we catch. These warnings can be recognized with undefined-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")))) 

Now we can wrap compilation forms in the corresponding handler-bind . For example, consider (compile nil (lambda () x)) with and without a handler:

 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 

We managed to compile the function and disable the warning of the undefined variable. However, keep in mind that you cannot just wrap defun in this. For instance,

 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 

However, if you eval the same defun (but I'm not saying what you need), the warning is silenced:

 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 

I don’t know exactly why this is so, but I hope someone can comment on the comments. I suspect this comes from the SBCL compilation forms in the REPL, which means that the defun body will compile before the whole form runs, so compilation happens before the handler is in place.

+3
source

Source: https://habr.com/ru/post/1496237/


All Articles