I like to write functions that dispose of failure cases early, before they do the main calculation, but I don't like to write cascading If statements. Here is a toy example of the sort of function I mean:
f[x_] :=
Block[{$TooBig},
If[! NumericQ[x], Return[$Failed]];
If[x > 10, Return[$TooBig]];
x!]
f /@ {5, 11, "x"}
{120, $TooBig, $Failed}
Now suppose rather than define f, I would like to use a pure function, so I write
Block[{$TooBig},
If[! NumericQ[#], Return[$Failed]];
If[# > 10, Return[$TooBig]];
#!] & /@ {5, 11, "x"}
{120, Return[$TooBig], Return[$Failed]}
The pure function returns at the appropriate points for all three arguments, but in the cases where Return should be called, it is returned unevaluated. I did not expect this behavior. Is it a bug or have missed a something I should be aware of?
I will point out that I do know how to work around this difficulty.
Block[{$TooBig},
If[! NumericQ[#], Return[$Failed, Block]];
If[# > 10, Return[$TooBig, Block]];
#!] & /@ {5, 11, "x"}
{120, $TooBig, $Failed}
I'm running V.10.2 on my system and don't have access to any older versions of Mathematica, so I don't know if this a version specific problem.
Throw/Catch, but the behaviour you observe can actually be exploited:check = If[Not@NumericQ[#], Return[$Failed]] &;thenfun[x_] := Block[{}, check[x]; x^2 ]. Suppose you have lots of functions likefun(I do) and you want to avoid re-typing the same sorts of argument checks. – Szabolcs Sep 04 '15 at 15:57Throw / Catchis a bad style whenReturn(with 2 args, may be) can be used. Of course, one must know how to use it correctly, and it is not very intuitive at first. – Leonid Shifrin Sep 04 '15 at 16:20Returnin this case ...", and then it would not be a direct duplicate. – Leonid Shifrin Sep 04 '15 at 16:42Return. – Szabolcs Sep 04 '15 at 16:45Block- the same happens also in the case ofWithorModule. So, I'd rather formulate it as "how would one return from some place of the pure function's body, usingReturn". In fact, when there is no scoping construct but one wants to return from p.f. usingReturn, a useful trick is to wrap the body of p.f. in an idleModule[{}, ...]or similar - which would then allow to useReturn[..., Module]. I've been using this trick many times. – Leonid Shifrin Sep 04 '15 at 17:13