5
$\begingroup$

I need to test some complicated conditions to calculate a Return value. But MMa doesn't let you Return[] from anywhere the way C++ does. The structure of my Module is similar to this:

foo[x_] := Module[{},
 Do[
  If[x == (n^2), Return[0]];
  If[x == (n^4), Return[1]],
  {n, 1, 5}];
 Return[2]];

If Return[] actually Return'd, foo[4] would return 0, but instead it returns 2.

Is there a way to do a return from an arbitrary place in the code?

I know that effete programmers will dislike my program structure, but I'm asking how to force the Return[], not how to restructure the program.

$\endgroup$
3
  • $\begingroup$ See the doc page of Return under Possible Issues. Due to how expressions are evaluated, "function call boundaries" are not as clear as in C++. $\endgroup$ – Szabolcs Apr 21 '15 at 18:59
  • 2
    $\begingroup$ Related: (29353), (6815), (18519), (58059) $\endgroup$ – Mr.Wizard Apr 21 '15 at 19:12
  • $\begingroup$ @Mr.Wizard yes, a well traveled topic. $\endgroup$ – rcollyer Apr 21 '15 at 19:14
6
$\begingroup$

As pointed out in the comments, Return only exits from the inner most construct. So, even though foo[4] hits the True clause in the first If statement, that only exits Do. Instead of using Return, use Throw/Catch, e.g.

bar[x_] := Module[{$myTag},
     Catch[
      Do[ 
       If[x == (n^2), Throw[0, $myTag]];
   If[x == (n^4), Throw[1, $myTag]]
       ,
       {n, 1, 5}
      ];
      Throw[2, $myTag]
  ,
  $myTag
 ]
];

Note, I use $myTag to insulate Catch against other throws. Then,

bar /@ {1, 2, 4, 7, 8, 16}
(* {0, 2, 0, 2, 2, 1} *)
$\endgroup$
6
$\begingroup$

If your Module were not inert you could use the second parameter of Return as follows:

foo[x_] :=
 Module[{n},
   Do[
    If[x == (n^2), Return[0, Module]];
    If[x == (n^4), Return[1, Module]],
    {n, 1, 5}
   ];
   Return[2]
 ]

foo[4]
0

Alternatively you could Return to CompoundExpression if you eliminate it from within the Do loop:

foo[x_] :=
  (
   Do[
    {If[x == (n^2), Return[0, CompoundExpression]],
     If[x == (n^4), Return[1, CompoundExpression]]},
    {n, 1, 5}
   ];
   Return[2]
  )

foo[4]
0

For a more complete explanation see:

$\endgroup$
9
  • $\begingroup$ That's why Return[0, Module] didn't work when I tried it. +1 $\endgroup$ – rcollyer Apr 21 '15 at 19:32
  • 1
    $\begingroup$ @rcollyer I'll admit it threw me at first too but I avoid null Module constructs like the plague so I hadn't come across it before. $\endgroup$ – Mr.Wizard Apr 21 '15 at 19:34
  • $\begingroup$ I see them occasionally, mostly on here, though, as most feel the need to put some sort of scoping construct around code when simple parentheses will do. $\endgroup$ – rcollyer Apr 21 '15 at 19:36
  • $\begingroup$ What does "inert" mean in this context? $\endgroup$ – Jerry Guern May 1 '15 at 5:02
  • 1
    $\begingroup$ @Mr.Wizard, I suspect that a response you'd find useful is a bit beyond my MMa sophistication. I couldn't make sense of rcollyer's Answer about tags at all. I got your code suggestion to Return stuff the way I wanted it to, but I still didn't understand your clarification about inert Modules or why my Module was inert or what the CompoundExpression thing did. I asked my Aug 11 question in the Comment above because there's SO much in MMa's design that seems to senseless and needlessly complicated to me that I wonder if there's some overarching method to WR's madness that I'm just not seeing.. $\endgroup$ – Jerry Guern Aug 15 '15 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.