From previous answers, replies and discussions it is known, while not formally documented (even in the most recent Wolfram Language Documentation Center), that Return can be used in a two-argument form in order to exit properly from specific places of pure function bodies.
For example:
Block[{i = 0}, While[i<10, Return[{"Exit Block", i}]]; "done While"]
returns
Return[{Exit Block,0}]
while, with the two-argument form:
Block[{i = 0},
While[i<10, Return[{"Exit Block", i}, Block]]; "done While"
]
the Block is immediately exited with the expected outcome:
{Exit Block,0}.
Analogously, trying Return[..., While]:
Block[{i = 0},
While[i < 10, Return[{"Exit Block", i}, While]]; "done While"
]
works as expected, so that only the enclosing While is exited and the subsequent instruction is executed, returning:
done While
Some more tests, though, show that this concept not always works.
For example, "If" cannot be exited:
Block[{i = 0}, If[i < 10, Return[{"Exit Block", i}, If]]; "done If"]
Return::nofunc: Function If not found enclosing Return[{Exit Block,0},If].
Hold[Return[{Exit Block,0},If]]
Apparently (at least in MMA 9), the two-argument form of Return works with:
Module
Block
Do
While
For
CompoundExpression
and does not seem to work with:
If
With
DynamicModule
Does anyone have a list of valid and invalid possibilities for the second argument of Return? Is there a clear rationale distinguishing what works from what does not work?
ThrowandCatch, with tags for clarity, instead. – Michael E2 Sep 04 '15 at 17:54Returnis a known piece of information (possibly linking to the question I mentioned). – Leonid Shifrin Sep 04 '15 at 17:55ThrowandCatchis a bad style in cases when the second argument ofReturncan be used, from the language viewpoint. It will likely also be slower, although I did not benchmark. – Leonid Shifrin Sep 04 '15 at 17:56Returncan be used quite elegantly in other cases (where of courseThrowandCatchcan also be used), like e.g. in this answer. – Leonid Shifrin Sep 04 '15 at 18:00Returncan also work with user-defined heads. So, the only way to understand this to to carefully read Rojo's answer, which contains full explanation. Re:WithvsBlock: the reason is thatWithreplaces the constants in code before evaluating the body, and then evaluates the code, so by the time code executes, there is noWithup in the stack. WithBlock, it is not so, because it has to undo its dynamic environment after its body executes. – Leonid Shifrin Sep 04 '15 at 18:15Returnworks / doesn't work for them, one by one, will be useful and will complement Rojo's answer. This is an interesting situation - personally, I'd keep this question to attract attention, and then merge with the ealier one once some answers appear here. – Leonid Shifrin Sep 04 '15 at 23:23