Why is Return not forcing an exit from my function? [duplicate]

Here is simplified version of my code that exhibits the behavior troubling me:

testFn[] := (
Do[
Print[i];
If[i > 3, Print["triggering result for true"]; Return [100]]
, {i, 1, 5}];
Return[200];
)

testFn[]
1
2
3
4
triggering result for true
200


Intuitively, once i is bigger than 3, it should evaluate the 2nd argument of the If and exit testFn, returning 100. However, although the 2nd argument of the If statement is getting evaluated, the function does not exit until it hits the Return[200].

I kind of guessed what might be the problem. The Return[100] is just exiting the Do, which seems to be confirmed by doing:

testFn[] := (
a = Do[
Print[i];
If[i > 3, Print["triggering result for true"]; Return [100]]
, {i, 1, 5}];
Print["a=" <> ToString[a]];
Return[200];
)

1
2
3
4
a=100
triggering result for true
200


If this is indeed what's happening, how can I make my code actually return from and exit testFn?

-

marked as duplicate by m_goldberg, bobthechemist, Michael E2, ubpdqn, RunnyKineJul 11 '14 at 1:32

Do Return[100, Module] Not just Return[100] see mathematica.stackexchange.com/questions/44585/… for more information –  Nasser Jul 10 '14 at 17:42
Take a look here: mathematica.stackexchange.com/questions/29353/… –  Szabolcs Jul 10 '14 at 19:00

Nasser in his comment is referring (somewhat cryptically) to an undocumented second argument of Return. You would use it this way.

test1[] :=
Module[{},
Do[Print[i]; If[i > 3, Print["i > 3"]; Return[100, Module]], {i, 1, 5}];
200]


However, I prefer to avoid undocumented stuff, so I recommend

test2[] :=
Catch[
Do[Print[i]; If[i > 3, Print["i > 3"]; Throw[100]], {i, 1, 5}];
200]

-
While I agree in general about the undocumented functionality, I think that in this particular case the use of Return with a second argument is a better solution. It is very unlikely that this feature will be discontinued, AFAICT. –  Leonid Shifrin Jul 10 '14 at 23:55
it is documented, but as WReach showed, it is hidden here reference.wolfram.com/language/ref/message/Break/nofunc.html The second argument is used here to specify that the return should be from the enclosing Module: In addition, I am not sure that using Throw/Catch to control programming logic is a good way to do things. These are meant to be used for exceptional cases, not normal flow. But this is for another subject :) –  Nasser Jul 10 '14 at 23:56
Instead of Throw/Catch you could equivalently use Reap/Sow (with some list logic on top). –  evanb Jul 11 '14 at 0:06
@Nasser. As someone who spent many years coding in Common Lisp, I don't share your view of Catch and Throw as being to restricted to handling exceptions, although that is certain a good use of them. I admit you have found (obscure) documentation for Return with a 2nd arg, but you can hardly expect the average Mathematica to be aware of it. –  m_goldberg Jul 11 '14 at 0:13