Under normal conditions, evaluating something that emits a Message
eg the evaluation of
1/0
that produces a Message
Power::infy
with text
Power: Infinite expression 1/0 encountered.
can be dealt with an expression like
Quiet[Check[1/0, $Failed]]
which returns $Failed
and invokes no Message
.
When evaluating Break[]
'naked' (outside any flow control loop) the front end issues a message Break::nofwd
with a text
Break: No enclosing For, While, or Do found for Break[]
and returns
Hold[Break[]]
I was expecting that after evaluating
Quiet[Check[Break[],$Failed]]
I'd obtain $Failed
(without any messages generated in the process).
Instead, I get the same message Break::nofwd
as before and the same output as before ie Hold[Break[]]
.
It is as if Check
doesn't do anything when Break
is its first argument.
Could someone please explain why I get this counter-intuitive result?
PS. I'm trying to pass Break[]
or a function that has Break[]
in its body as an argument to another function with a While
loop in its body. The former function would ideally force the later function to exit the loop without any messages.
f[___]:=Break[]
SetAttributes[g, HoldAll]
g[func_] := Module[{res = Quiet[Check[func, $Failed]], j = 0},
While[
FailureQ[res] && j < 10,
res = Quiet[Check[func, $Failed]];
j++
];
j
]
Evaluating g[f[]]
returns the familiar Break::nofwd
and returns Hold[Break[]]
; I understand that this happens because res = Quiet[Check[func, $Failed]]
gets evaluated during the initialization of Module
.
Break
is a version of localGoto
, and when there is no enclosing construct that stops it, it bubbles up, just like exceptions or aborts, except it is neither of those, so can't be caught using any of theCatch
,Check
, etc. So it would probably need a separateCheck
-like function, like e.g. this:SetAttributes[checkBreak, HoldFirst]; checkBreak[code_, failExpr_] := Module[{breakUsed = True, result}, Do[result = code; breakUsed = False, {1}]; If[breakUsed, failExpr, result]]
. $\endgroup$ – Leonid Shifrin Jul 26 '18 at 10:26Break[]
? If it is to force breaking the loop, thenf
could just return$Failed
and you could just checkres
right beforej++
usingIf[FailureQ[res],Break[]]
. $\endgroup$ – Hector Jul 26 '18 at 10:34Do
can be replaced with any other built-in that breaks withBreak[]
? $\endgroup$ – user42582 Jul 26 '18 at 12:19f
is a stand-in for code that usesImport
to scrape html content and sometimes it returns error messages $\endgroup$ – user42582 Jul 26 '18 at 12:23For
orWhile
etc. in appropriate form. I usedDo
since it is simple and I can easily ensure that the code is executed exactly once. In general, the need for such a construct is rather weird - I never needed that. But the observation itself, thatBreak[]
andContinue
represent another type of signals, is important. $\endgroup$ – Leonid Shifrin Jul 26 '18 at 14:29