Re: Return inside Do, For and While
- To: mathgroup@smc.vnet.net
- Subject: [mg12600] Re: [mg12568] Return inside Do, For and While
- From: David Withoff <withoff@wolfram.com>
- Date: Mon, 25 May 1998 14:25:10 -0400
> I am going through the Power Programming book by Wagner and have a > question about Return[value]. > > According to the documentation, it is supposed to cause a "function" to > return a value. I have always used it to exit and return a value from > a Module or With. Because I almost never use Do, For or While except > when following a textbook, I had never tried to use Return from inside > a loop. > > For example, consider the following code that tests a list of integers > to see if they are all odd: > > allOdd[x_List]:=Module[{i=1}, > > Do[If[!OddQ[x[[i]]], > Return[False]]; > i++, > {Length[x]}]; > > Return[True]] > > This function returns True no matter what the list is. Consider the > following modification: > > allOdd[x_List]:=Module[{i=1}, > If[!Do[If[!OddQ[x[[i]]], > Return[False]]; > i++, > {Length[x]}], > Return[False]]; > > Return[True]] > > This makes it clear that Wolframs definition of a "function" includes > loops (Do, While, For). > > Does anyone know what other built in objects qualify as "functions" for > purposes of using Return? Return[expr] is used to return expr from a function that you have defined, or to exit from an enclosing CompoundExpression, Do, For, Scan, or While expression. See that web page for additional notes and examples. If you need to transfer program control to an unambiguous place outside of a function, the best way to do that is with Throw and Catch. The Catch function allows you to specify where the Throw function should throw to. In contrast with procedural languages, where "return" pops one level up the subroutine return stack, there isn't an intuitively obvious place in a functional programming language for "return" to return. This ambiguity is addressed in functional programming languages (such as various dialects of LISP) by including heuristics to try to guess the intended return destination, or by providing language constructs (such as labeled blocks or catch-like functions) that allow for specifying the return destination. In Mathematica you can use Throw and Catch: In[1]:= allOdd[x_List]:= Catch[Module[{i=1}, Do[If[!OddQ[x[[i]]], Throw[False]]; i++, {Length[x]}]; Throw[True]]] In[2]:= allOdd[{1,3,6,11}] Out[2]= False or you could add a second level of Return (to return both from the Do loop and from your function): In[3]:= allOdd[x_List]:=Module[{i=1}, Do[If[!OddQ[x[[i]]], Return[Return[False]]]; i++, {Length[x]}]; Return[True]] In[4]:= allOdd[{1,3,6,11}] Out[4]= False In[5]:= allOdd[{1,5,9}] Out[5]= True or you could use the two-argument form of Return to specify that the Return should return from the enclosing Module: In[6]:= allOdd[x_List]:=Module[{i=1}, Do[If[!OddQ[x[[i]]], Return[False, Module]]; i++, {Length[x]}]; Return[True, Module]] In[7]:= allOdd[{1,3,6,11}] Out[7]= False In[8]:= allOdd[{1,5,9}] Out[8]= True but with just Return[False] the behavior will depend on the implied return destinations that have been programmed into the system, which may not be what you had expected. The implied return destinations that are used in Mathematica match the expected destination perhaps ninety-five percent of the time (and I personally don't know how to to do any better than that), but if you need to return to an unambiguous place, you might want to try Throw and Catch, or some other construction. Dave Withoff Wolfram Research