This question already has an answer here:

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_] :=
    If[! NumericQ[x], Return[$Failed]];
    If[x > 10, Return[$TooBig]];
f /@ {5, 11, "x"}
 {120, $TooBig, $Failed}

Now suppose rather than define f, I would like to use a pure function, so I write

  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.

  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.


marked as duplicate by Leonid Shifrin, Community Sep 4 '15 at 15:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ Duplicate? mathematica.stackexchange.com/q/29353/12 $\endgroup$ – Szabolcs Sep 4 '15 at 15:40
  • $\begingroup$ @Szabolcs. Sure looks like one. $\endgroup$ – m_goldberg Sep 4 '15 at 15:51
  • $\begingroup$ Some might argue that this is bad style, or that one should really use Throw/Catch, but the behaviour you observe can actually be exploited: check = If[Not@NumericQ[#], Return[$Failed]] &; then fun[x_] := Block[{}, check[x]; x^2 ]. Suppose you have lots of functions like fun (I do) and you want to avoid re-typing the same sorts of argument checks. $\endgroup$ – Szabolcs Sep 4 '15 at 15:57
  • $\begingroup$ Since it is not explicitly mentioned, Return[value, Block] solves the problem: Block[{\$TooBig}, If[! NumericQ[#], Return[\$Failed, Block]]; If[# > 10, Return[\$TooBig, Block]]; #!] & /@ {5, 11, "x"} $\endgroup$ – user8074 Sep 4 '15 at 16:03
  • 2
    $\begingroup$ @user8074. It is most certainly explicitly mentioned. $\endgroup$ – m_goldberg Sep 4 '15 at 16:05