0
$\begingroup$

I have an iterated computation running in a while loop, which is bound to fail at some point, at which point I want it to stop, e.g.

currentSolution = 0;
Block[{i = -3},
 While[i < 3,
  correction = 1/i;
  currentSolution += correction;
  i++;
  ];
 currentSolution
 ]

Of course in my actual application the computation is more complicated, I don't know ahead of time when it will fail, and the While condition depends on result too.

I want the While loop to stop at any error message, suppress Mathematica's messages and show my own.

Furthermore I want to be able to easily customise this, i.e. turn off the error checking completely or change the messages that are shown or that trigger the error.

For this I've written the general code:

Attributes[checkError] = {HoldFirst};
checkError[{expr_, failCode_}, myErrorMessage_, myErrorMessageParams_,
   messagesIgnored_, messagesNotShown_, messagesShown_] := 
 If[$CheckError === False, expr, 
  Quiet[Check[Quiet[expr, messagesIgnored], failCode;
    Message[myErrorMessage, myErrorMessageParams];
    Return[$Failed, Block]], messagesNotShown, messagesShown]]

and a more specific one that uses the above:

Attributes[checkError2] = {HoldFirst};
checkError2[expr_, params_] := 
 checkError[{expr, currentSolution = $Failed}, my::message, 
  params, $MessagesIgnored, $MessagesNotShown, $MessagesShown]

$CheckError = True;
$MessagesIgnored = {};
$MessagesNotShown = All;
$MessagesShown = {my::message, General::stop};
my::message = "Failed at `1`!";

which I would want to use as:

currentSolution = 0;
Block[{i = -3},
 While[i < 3,
  correction = checkError2[1/i, i];
  currentSolution += correction;
  i++;
  ];
 currentSolution
 ]

The intention is for this to show my::message and output $Failed.

There are some problems with this code though:

at the above it doesn't recognise the messages in messagesShown nor myErrorMessage:

enter image description here

When I explicitly copy {my::message, General::stop} into messagesShown in checkError these errors disappear and it outputs $Failed. When I do the same with my::message that also displays. But for instance replacing messagesShown with Evaluate@messagesShown does not work.

Another issue is that even if it worked, messagesIgnored would indeed be ignored by Check because the Quiet is inside, but they would also obviously not be shown, which is not what I want, that should be controlled by messagesNotShown and messagesShown. Unlike for Quiet there is no additional argument for Check that controls which messages not to check for.

How do I fix these issues and make this code work as intended?

$\endgroup$
  • $\begingroup$ @Alan No particular reason (but I just checked that with Module it gives the same error). $\endgroup$ – Jansen Nov 5 '18 at 15:15
  • $\begingroup$ @Alan What do you mean? I am Checking the errors that this code is supposed to encounter, while the errors that this code itself generates are actual errors that preventie it from functioning. $\endgroup$ – Jansen Nov 5 '18 at 16:16
  • $\begingroup$ reference.wolfram.com/language/ref/Check.html $\endgroup$ – Alan Nov 5 '18 at 18:23
  • $\begingroup$ @Alan Yes I know about Check, it's there in between two Quiets in my code checkError. Messages blocked by the inner Quiet are ignored by Check (but are also not printed obviously, which is not what I want), while the outer Quiet of course doesn't affect Check. If you are trying to say that Check already has all the functionality that I want then I don't see it. $\endgroup$ – Jansen Nov 5 '18 at 18:51
  • $\begingroup$ Do named message groups not meet your needs? Sorry if not. $\endgroup$ – Alan Nov 5 '18 at 20:41

Your Answer

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

Browse other questions tagged or ask your own question.