5
$\begingroup$

Check[expr,failexpr,checkedMessages] will evaluate expr and if it encounters any of the messages in checkedMessages it will evaluate failexpr and return that instead.

But how can I Check for all messages except let's say one?

Quiet has the syntax Quiet[expr,All,notQuiet] that will suppress all messages except those in notQuiet, but Check does not have this option.

A workaround is to use Quiet inside Check:

Check[Quiet[expr,ignoredMessages],failexpr,checkedMessages]

which will trigger for any message that is contained in checkedMessages but not in ignoredMessages. However this has the unintended side effect of also (obviously) Quieting the ignoredMessages.

So for instance the desired function

myCheck[expr_,failexpr_,checkedMessages_,ignoredMessages_]:=..?

should do this:

myCheck[1/0,1,All,{}]
(* show message Power::infy *)
(* return 1 *)

but

myCheck[1/0,1,All,{Power::infy}]
(* show message Power::infy *)
(* return ComplexInfinity *)

(This is a more succinct question about one of the issues in this question)

$\endgroup$
  • 2
    $\begingroup$ I'm pretty sure Check[] does not abort an evaluation but let's it run its course; then it failexpr is evaluated. Catch@Check[Check[res = expr, Throw@res, ignoredMessages], failexpr, messages] might work for you. (It's probably better to use Throw and Catch with tags.) $\endgroup$ – Michael E2 Nov 6 '18 at 11:34
  • $\begingroup$ @Kuba Sorry you and Michael are right of course that Check doesn't abort the evaluation, that was sloppy. I don't need it to though, I've added two examples. $\endgroup$ – Jansen Nov 6 '18 at 13:06
  • $\begingroup$ @MichaelE2 Sorry I shouldn't have written that Check aborts the evaluation, it doesn't and I don't need it to. I want the functionality of Check but just with the addition that it can check for all messages except some specified list. Writing your suggestion as myCheck[expr_, failexpr_, checkedMessages_,ignoredMessages_]:= Block[{res}, Catch@Check[Check[res =expr, Throw@res, ignoredMessages], failexpr,checkedMessages]] gives an error in my examples regarding All. This can be solved by replacing checkedMessages by Evaluate[checkedMessages/.All->Sequence[]]... $\endgroup$ – Jansen Nov 6 '18 at 13:21
  • $\begingroup$ @MichaelE2 ..and similar for ignoredMessages, but then it returns ComplexInfinity in both examples above. $\endgroup$ – Jansen Nov 6 '18 at 13:21
  • $\begingroup$ The problem with my proposal is that when multiple messages are emitted, some to be ignored and some not, they are all ignored. I suppose the desired behavior if any checkedMessages are emitted is to return failexpr, yes? $\endgroup$ – Michael E2 Nov 6 '18 at 13:57
2
$\begingroup$

Method 1

ClearAll[myCheck];
SetAttributes[myCheck, HoldAll];
myCheck[expr_, failexpr_, checkedMessages_List, 
   ignoredMessages_List] := Module[{res, c, i},
   c = Alternatives @@ HoldForm /@ Unevaluated@checkedMessages /. 
     All -> _;
   i = Alternatives @@ HoldForm /@ Unevaluated@ignoredMessages /. 
     All -> _;
   Check[res = expr, 
    If[AnyTrue[$MessageList, MatchQ[#, Except[i, c]] &], failexpr, 
     res]]
   ];
myCheck[expr_, failexpr_, checkedMessages_, ignoredMessages_List] := 
  myCheck[expr, failexpr, {checkedMessages}, ignoredMessages];
myCheck[expr_, failexpr_, checkedMessages_, ignoredMessages_] := 
  myCheck[expr, failexpr, checkedMessages, {ignoredMessages}];

myCheck[0/0, "Oops!", All, Power::infy]

Examples:

Power::infy: Infinite expression 1/0 encountered.

Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

(* Out[]= "Oops!" *)
myCheck[0/0, "Oops!", All, {Power::infy, Infinity::indet}]
Power::infy: Infinite expression 1/0 encountered.

Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

(* Out[]= Indeterminate *)

Method 2

I might prefer a pattern-oriented check.

ClearAll[myCheck2];
SetAttributes[myCheck2, HoldAll];
myCheck2[expr_, failexpr_, msgPat_] := Module[{res, failPat},
   failPat = 
    Hold[msgPat] /. {hm : HoldForm[_MessageName] :> hm, 
       m_MessageName :> HoldForm[m]} // ReleaseHold;
   Check[res = expr, 
    If[AnyTrue[$MessageList, MatchQ[#, failPat] &], failexpr, res]]
   ];

Examples:

myCheck2[0/0, "Oops!", Except[Power::infy]]
Power::infy: Infinite expression 1/0 encountered.

Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

(* Out[]= "Oops!" *)
myCheck2[0/0, "Oops!", Except[Power::infy | Infinity::indet]]
Power::infy: Infinite expression 1/0 encountered.

Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

(* Out[] = Indeterminate *)
myCheck2[Sin[x, y], "Oops!", Except[_::"argx"]]
Sin::argx: Sin called with 2 arguments; 1 argument is expected.

(* Out[]= Sin[x, y] *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.