When must I use the Return function?

Return is surprisingly under-documented, but I would still recommend reading Return as a start. Return has an undocumented feature which you can read about here

But none of the above really answers the question. Frankly, I can't come up with a situation that absolutely requires the use of Return, although I can think of several where using Return is convenient.

That said, I will try to give a rule-of-thumb. Use Return to terminate the evaluation of a compound expression inside a function at any point before the final argument of the compound expression is evaluated. Does that read as gibberish? To make sense of it, recall that a; b; c is actually the short form of CompoundExpression[a, b, c], which returns whatever c evaluates to. To get a; b; c to stop after evaluating b and return, write a; Return[b]; c instead.

Of course, in normal usage Return will be placed in some kind of conditional construct. For example,

f[x_] := (a; If[x > 0, Return[a]]; b)
{f[42], f[-42]}
{a, b}

But this can be rewritten, as all the cases I can think of, to eliminate the use of Return.

g[x_] := If[x > 0, a, b]

So when is it practical to use Return in "real" code? I find myself using Return in the definitions of functions that have non-standard evaluation; e.g., functions that have the the HoldAll attribute. In such functions, there is a need to validate arguments that have been passed in. It is convenient to do this up front, using Return to cut short evaluation should a bad argument be found. Here is a rather contrived example.

Clear @ h
SetAttributes[h, HoldAll];
h::badarg = "`1` = `2` is not valid";
h[x_, y_] :=
  Module[{result = $default},
If[! MatchQ[x, _Integer /; x > 0], Message[h::badarg, "x", x]; Return[$Failed]];
    If[! MatchQ[y, _Real], Message[h::badarg, "y", y ]; Return[$Failed]];
    (* do some long computation here *)
    result]

h[42, 42.]
$default
h[-42, 42.]

h::badarg: x = -42 is not valid

 $Failed
h[42, 42]

h::badarg: y = 42 is not valid

 $Failed

Another thing good to know about Return is that it is not a function in the ordinary Mathematica sense. It's a symbol which has special meaning to the Mathematica evaluator and which causes a side effect. If Return were an ordinary function a; Return[b]; c would be the same as a; b; c.

The non-functional behavior of Return is demonstrated by the following rather peculiar sequence of evaluations.

expr = CompoundExpression[a, Return[b], c];
Return[b]
OwnValues @ expr
{HoldPattern[expr] :> Return[b]}
expr
b

I think the most direct answer to this question is: rarely.

Incorrect Usage

A great majority of the appearances of Return that I see are either entirely superfluous or an indication of code in need of refactoring. For example I frequently see something like:

fn[x_] :=
  Module[{vec},
    vec = {1, 2, 3};
    Do[vec[[i]] *= x, {i, 1, Length[vec]}];
    Return[vec]
  ]

Return is superfluous here as omitting it will produce the same result. And of course the rest this code would be written far more simply which is often true in such cases.

Correct Usage

Return does have its place, as does its sister function Break. These functions are the most direct way to exit an ongoing incremental evaluation, and optionally return a value. It is important to understand how they work but there are already questions on that subject:

  • How does Return work?
  • What can I use as the second argument to Return in my own functions?

Although mostly undocumented I often, even typically, use these functions with additional parameters:

  • Is there a Break[] equivalent for short-circuiting in Table?

This not only extends the application of Return and Break but it more clearly defines the behavior of the operation which may make it more robust through version changes.

One must understand the order of evaluation and operation of Mathematica functions to effectively use Return and Break. For example it is not possible to Break[] out of a Map operation because Map first applies the function, then evaluates the expression, as explained here:

  • Scan vs. Map vs. Apply

However Scan does use an incremental evaluation which means that we can Return or Break from it:

Scan[
  If[# > 2, Return[#]] &,
  {1, 2, 3, 4, 5}
]
3

Critically, though not illustrated, the Function is never applied to elements 4 and 5.

The question title is not when should I use Return but rather when must I use return and that is even more rare, if ever. The operation above can also be written using Throw and Catch:

Scan[
  If[# > 2, Throw[#]] &,
  {1, 2, 3, 4, 5}
] // Catch
3

(Like Return using the second parameter of Throw and Catch will make this operation more robust.)

Exclusive Usage

I am not prepared to say that there is ever a case where one must use Return as there are so often clever alternative methods in Mathematica. However one example where it is at least far easier to use Return is if it is not practical to insert a Catch at an arbitrary place in the evaluation.

Suppose we have a function with multiple internal operations which itself accepts a function:

func[f_, dat_] := Array[f, #, #2] & ~MapIndexed~ dat ~Flatten~ {2}

func[f, {4, 1, 3}]
{{f[1], f[2], f[3]}, {f[2], f[4]}, {f[3], f[5]}, {f[4]}}

Without modifying func we can use Return to affect the evaluation in different ways:

func[If[# > 4, Return[{0, 7, 9}, Array], #] &, {4, 1, 3}]

func[If[# > 4, Return[{{1, 2}, {3}}, MapIndexed], #] &, {4, 1, 3}]

func[If[# > 4, Return["foo", func], #] &, {4, 1, 3}]
{{1, 2, 0}, {2, 7}, {3, 9}, {4}}

{{1, 3}, {2}}

"foo"

I apologize for obfuscation from what was perhaps a poorly chosen example function, but the point is that we can exit from and return a value for an individual use of Array, or the one call to MapIndexed, or the entire function func.

Note that there was no example of Flatten for the parameter of Return because it does not work:

func[If[# > 4, Return["x", Flatten], #] &, {4, 1, 3}]

Return::nofunc: Function Flatten not found enclosing Return[x,Flatten]. >>

Hold[Return["x", Flatten]]

The reason for this is complicated and it is the subject of Rojo's answer found in the second bulleted link from the top of this post.


I think I find a situation that almost absolutely requires the use of Return. Using Return seems to be the only documented way to exit from a Dialog and return a value:

enter image description here

Sadly(?) there's a undocumented function ExitDialog that can be used for the task, too. (Still, Return and ExitDialog have subtle difference, read this post for more information.)