2
$\begingroup$

Please, consider the following code :

k = 0;
ret = Catch[
  Check[
    data = 1/k;
    Print[Pi] ;
    Throw[data, "RETURN"];
    , Throw @ $Failed
    ];
  , "RETURN"
  ]

In my mind, it should work this way:

  • if k = 1 (1) data = 1 (2) Check does nothing (because no message has been generated) (3) Catch catches data (4) ret = 1

  • if k = 0 (1) data = Complex Infinity (2) Check wakes up because a message has been generated (Power::infy) and throws $Failed (3) but this throw has not the tag "RETURN", therefore it is not caught by Catch and a message (Throw::no catch) is generated.

On the opposite, what happens is:

  • if k = 1 ... as expected

  • ik k = 0 ... ret = ComplexInfinity

To detect the point where I'am reasoning wrong, I added the Print command inside: Pi is printed even when k = 0 so I conjecture that Check evaluates its first argument, not returning the failexp until the whole computation has been completed. Two question:

  • is this behaviour related to the HoldAll attribute of Check ?

  • how can I break at the generation of the first message ?

$\endgroup$
  • $\begingroup$ What about ret=Check[1/k,Throw@$Failed]? $\endgroup$ – unlikely Mar 17 '16 at 6:36
4
$\begingroup$

Check doens't stops the evaluation of its first arguments at the first message generated

Check[1/0; Print["inf"], err]
During evaluation of In[497]:= Power::infy: Infinite expression 1/0 encountered. >>

During evaluation of In[497]:= inf

err

I think you have to put a Check around every expression that could generate a message, with some convenience function

CheckAndThrow = 
 Function[expr, Quiet@Check[expr, Throw@$Failed], {HoldAll}]

(
 1 + 1;
 1/0 // CheckAndThrow;
 0^0 // CheckAndThrow;
 1 + 1
 )

Maybe someone else know a way to intercept a message generation and Throw automatically.


From the comment of @rcollyer and the links (1 and 2) provided

"Message" [handler] is invoked for every generated message and passes one argument of the form Hold[..., ...] to the handler function, with the second element set to False for quieted messages.

So, to get the effect you want, I think you can guard your code, potentially raising messages, in this way

Internal`HandlerBlock[
 {"Message", Replace[#, _[_, True] :> Throw@$Failed] &}},

 (* ... code here ... *)

]

This will throw $Failed for every not Quiet-ed message generated inside the guarded block. Because of the general convention about ...Block of code, at the end of the guarded block, this message handling behavior is discared and any previous message handling routine restored.

$\endgroup$
  • 1
    $\begingroup$ Right. To Throw/Abort on a message, you use an Internal`HandlerBlock, like in this answer. $\endgroup$ – rcollyer Mar 17 '16 at 13:17
  • $\begingroup$ @rcollyer I suspected that it was an "internal" method... $\endgroup$ – unlikely Mar 17 '16 at 13:39
  • $\begingroup$ Internal`HandlerBlock seems to be an undocumented feature (at present moment, I'm using ver. 8.0.1.0) and googling doesn't help much. Please, can you provide any reference to study ? $\endgroup$ – mitochondrial Mar 17 '16 at 20:57
  • 2
    $\begingroup$ @mitochondrial Check the answer pointed by rcollyer. I think its the only and best "documentation" available. $\endgroup$ – unlikely Mar 17 '16 at 21:00
  • 1
    $\begingroup$ @mitochondrial I also expanded a bit my answer. $\endgroup$ – unlikely Mar 17 '16 at 21:20

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.