# How to exit from the innermost enclosing pure function?

Here is what I tried to do:

Scan[Function[x,
Scan[Function[y,
If[y == 2, Return[]];
(* Do something useful *) Print[y]],
x]],
{{1, 2, 3}, {4, 5, 6}}]


My intention was that the Return[] exited from the innermost enclosing pure function (having the parameter y). Instead, it terminated execution of the innermost enclosing Scan and proceeded to the next iteration of the outermost Scan.

1 4 5 6


The documentation for Return says:

Return exits only the innermost construct in which it is invoked

I do not see why the innermost Scan is considered the innermost enclosing construct here. If, CompoundExpression and Function look like more inner constructs.

Question 1: Could you give a more clear explanation of what precisely Return does?

After I realized that Return does not do what I want here, I looked for workaround, and found several ones:

(a) I can restructure the body of the innermost pure function:

Scan[Function[x,
Scan[Function[y,
If[y != 2,
(* Do something useful *) Print[y]]
],
x]],
{{1, 2, 3}, {4, 5, 6}}]


In this case it looks straighforward, but becomes messy if I have more nested control flow operators and multiple points where I might need to exit.

(b) I can use infamous Label and Goto constructs:

Scan[Function[x,
Scan[Function[y,
Module[{exit},
If[y == 2, Goto[exit]];
(* Do something useful *) Print[y];
Label[exit];
]],
x]],
{{1, 2, 3}, {4, 5, 6}}]


(c) I can use Throw and Catch constructs:

Scan[Function[x,
Scan[Function[y,
Module[{exit},
Catch[
If[y == 2, Throw[Null, exit]];
(* Do something useful *) Print[y],
exit]]],
x]],
{{1, 2, 3}, {4, 5, 6}}]


Question 2: Which of them would you prefer? Or can you suggest a better way to do this?

-

You can specify the evaluation of which construct should be stopped by Return by providing the second argument (undocumented?). For example,

Scan[Function[x,
Module[{},
Print[x];
Return[$Failed, Module]; Print[-x]]], {1, 2, 3}]  or Scan[Function[x, Print[x]; Return[$Failed, CompoundExpression];
Print[-x]],
{1, 2, 3}]

-
It isn't documented under Return but it is here: Return::nofunc –  Chris Degnen Dec 5 '13 at 17:11

It's hard to reply without larger context, but if you are not restricted to use pure functions, then one option would be to use the pattern-defined overloaded function instead:

ClearAll[fun];
fun[2] := Null;
fun[x_] := ((*Do something useful*)Print[x])


Then, you just write:

Scan[Function[x, Scan[fun, x]], {{1, 2, 3}, {4, 5, 6}}]


In fact, you can as well define fun at run-time, if you need.

As to Return, I can recommend this, and particularly this discussions for more details on how it works.

-

I would use Catch and Throw if pressed to choose, without the 'exit' :

Scan[Function[x,
Scan[Function[y,
Catch[If[y == 2, Throw[Null]];
(*Do something useful*) Print[y]]
],
x]],
{{1, 2, 3}, {4, 5, 6}}]


or simply,

Scan[Function[x,
Scan[Function[y,
If[y == 2, Null,
(*Do something useful*) Print[y]]
],
x]],
{{1, 2, 3}, {4, 5, 6}}]

-