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:
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?

Moduleit gives the same error). – Jansen Nov 05 '18 at 15:15Checking 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. – Jansen Nov 05 '18 at 16:16Check, it's there in between twoQuiets in my codecheckError. Messages blocked by the innerQuietare ignored byCheck(but are also not printed obviously, which is not what I want), while the outerQuietof course doesn't affectCheck. If you are trying to say thatCheckalready has all the functionality that I want then I don't see it. – Jansen Nov 05 '18 at 18:51Checkfor all messages except one or several.Quietsupports this withQuiet[...,All,notQuiet]butCheckdoes not. But I also don't understand why the messages are not recognised in my code. – Jansen Nov 06 '18 at 08:31my::messageevaluates to the string"Failed at `1`"before theHoldAllattribute fromQuiethas a chance to prevent this. To work around this, you have to pass in the messages in some held form and then carefully insert them intoQuiet, e.g. using,myQuiet[expr_,Hold[messages__]]:=Quiet[expr,{messages}],Attributes[myQuiet]={HoldFirst}wheremessageswill beHold[my::Message,…]– Lukas Lang Nov 10 '18 at 09:56Internal`HandlerBlock](https://mathematica.stackexchange.com/a/1545) to build your ownCheck-like function – Lukas Lang Nov 10 '18 at 10:05