Re: Re: Re: Re: Return in function
- To: mathgroup at smc.vnet.net
- Subject: [mg106131] Re: [mg106110] Re: [mg106045] Re: [mg106018] Re: Return in function
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Sat, 2 Jan 2010 05:06:09 -0500 (EST)
- References: <hftbe9$cjh$1@smc.vnet.net> <200912300915.EAA17319@smc.vnet.net>
Well, I do occasionally use Return, but admittedly not very often. Ironically, it seems like Return was mostly designed to ease the transition to Mathematica for users with procedural background, who are very likely to use it since they don't know about other ways to accomplish their goals. But I agree that you have a point. Regards, Leonid On Fri, Jan 1, 2010 at 2:38 AM, DrMajorBob <btreat1 at austin.rr.com> wrote: > > Here is my guess. Making Return work in a block of code is not > > difficult... > > Subsequently, I think you explained why it's not not only difficult, but > impossible. > > So we're back to my original advice: don't USE Return, and you won't have > to worry about it. > > Bobby > > On Thu, 31 Dec 2009 22:23:20 -0600, Leonid Shifrin <lshifr at gmail.com> > wrote: > > > Hi Bobby, > > > > On Thu, Dec 31, 2009 at 10:26 AM, DrMajorBob <btreat1 at austin.rr.com> > > wrote: > > > >> Explanations hidden in technical reports do not count as documentation, > >> and > >> neither do private communications between experts. (For the same > >> reason.) > >> > >> If the behavior of Return is not a bug, it should be documented where > >> users > >> are likely to see it when looking up "Return" in Help. > >> > > > > Agreed. You have a point, and I also think that the documentation for > > Return > > is inadequate. That said, most if not all of people participated in the > > discussion in this thread are advanced Mathematica users, to say the > > least. > > And although I don't know the exact circumstances and context in which > > the > > OP (Daniel) encountered this problem, I have no doubt that he could and > > did > > find a workaround even before posting the question. > > > > I think that we all ask questions like this not because we are totally > > stuck > > and see no way out, but in order to understand the system better, > > including > > its darker corners. For a system as large and complex as Mathematica, I > > think it is unavoidable to have a large number of such pitfalls, > > especially > > because the system is evolving. Now, there are two ways of answering > > this > > sort of questions: one is to rightly blame the documentation (which > > generally is by far not the worst among those for the software I use) , > > and > > another is to give some perhaps not hundred percent authoritative or > > "official" but reasonable explanations. I find the latter more > > constructive, given that it is the latter that most people with > > sufficient > > Mathematica background seem to be interested in. > > > > > >> The explanation below seems to be "retrospective cataloging of observed > >> behavior", not "designed behavior". > > > > > > I disagree. I think it is the designed behavior. And the fact that it has > > been documented (albeit in a technical report) as early as in 1992, I > > think > > speaks in favor of my guess. The problem is that the semantics of > > function > > calls is emulated in Mathematica by the rule substitution. OTOH, for the > > consistency of the system, Return must obey the standard mechanics of > > evaluation process, as any other head. Since the decision do discard > > Return > > is comming from the "external" to Return context, you can not just define > > built-in DownValues for Return. Moreover, since Return performs a > > non-local > > jump, you can not universally define UpValues for Return either. What are > > your choices then? > > > > Here is my guess. Making Return work in a block of code is not difficult > > - > > all you have to do is to define an extra rule for CompoundExpression, > > which > > will make it ignore its arguments standing after Return. In this way you > > avoid the complexities and overhead of checking for Return in each of the > > many kinds of scoping constructs. By not discarding Return at this stage > > you > > make it possible to nest (break out of nested CompoundExpression-s): > > > > In[1]:= (c; d; (a; b; Return[e]); f) > > > > Out[1]= Return[e] > > > > But this means that Return must be an idle head. Who will then be > > responsible for discarding Return at the end? Not Return itself, and not > > the > > scoping constructs which presumably know nothing about Return. It may be > > that a universal solution to this problem does not exist or is very > > hard to > > find/prove correct. > > > > The design decision concerning Return seems to have been made such in > > order > > for a user of Return to see no difference from the action of Return in > > other > > languages, *in most sensible cases*. Since the overwhelming majority of > > uses of Return are inside some user-defined functions (rules), a single > > simple rule of discarding Return generated through application of > > user-defined rules covers all such cases. This seems to be one of the > > cases > > where generality has been traded for simplicity, and in this particular > > case > > this looks like a very reasonable solution to me.I wonder how many > > beginners > > or even intermediate Mathematica users ever stumbled upon anything like > > Daniel's original example - I think very few. > > > >> > >> > >> This seems to explain the behavior of Return in all cases (at least in > >> my > >>> experience). > >>> > >> > >> Exactly. Your next experience may be different, and you'd simply add it > >> to > >> the list. > >> > > > > True. But notice that the list is quite short, and it summarizes > > experiences > > of several people, not just me. And somehow in the case of Return I doubt > > that it will grow significantly, if at all. > > > > Regards, > > Leonid > > > > > > > >> > >> Bobby > >> > >> > >> On Thu, 31 Dec 2009 02:15:35 -0600, Leonid Shifrin <lshifr at gmail.com> > >> wrote: > >> > >> Norbert, > >>> > >>> Had you followed the development of this thread and you would have > >>> noticed > >>> my post where I argued that this is *not* a bug, although indeed a > >>> rather > >>> unintuitive feature. The main authoritative source of information on > >>> this > >>> matter (apart from the standard documentation) seems to be the > >>> technical > >>> report by David Withoff named "Mathematica internals", of 1992. After > >>> making > >>> my post I was additionally informed by Fred Simons that the behavior of > >>> Return has been very nicely summarized by Allan Hayes back in 2002. I > >>> think > >>> this may be of general interest so I repeat it here: > >>> > >>> If Return[x] is generated as a value in Do or Scan then x is > >>> immediately > >>> returned; > >>> If Return[x] is generated as an entry in CompoundExpression or as a > >>> value > >>> of > >>> the body of a While or For loop then Return[x] (not x) is immediately > >>> returned; > >>> If Return[x] is generated as the value of a user-defined function then > >>> the > >>> function returns x (not Return[x]) > >>> Otherwise Return[x] behaves as a ordinary expression. > >>> > >>> This seems to explain the behavior of Return in all cases (at least in > >>> my > >>> experience). > >>> > >>> Regards, > >>> Leonid > >>> > >>> > >>> > >>> On Wed, Dec 30, 2009 at 12:15 PM, Norbert P. <bertapozar at gmail.com> > >>> wrote: > >>> > >>> On Dec 11, 3:46 am, dh <d... at metrohm.com> wrote: > >>>> > Version 7.0.1 > >>>> > > >>>> > Hello, > >>>> > > >>>> > I am not sure if this is a feature or a bug. If you use Return in an > >>>> > > >>>> > anonymous function, not only the return value is returned, but also > >>>> > > >>>> > "Return" itself. Consider: > >>>> > > >>>> > (If[# == 2, Return[a]; #, #]) & /@ {1, 2, 3} > >>>> > > >>>> > this gives: > >>>> > > >>>> > {1, Return[a], 3} > >>>> > > >>>> > The same thing happens with: > >>>> > > >>>> > Function[x, If[x == 2, Return[a]; x, x]] /@ {1, 2, 3} > >>>> > > >>>> > However, the following works as expected: > >>>> > > >>>> > f[x_] := (If[x == 2, Return[a]; x, x]); > >>>> > > >>>> > f /@ {1, 2, 3} > >>>> > > >>>> > Daniel > >>>> > >>>> Even though I think that it's a bad habit to use Return, it might be > >>>> useful at times. And since it's been in Mathematica since the version > >>>> 1, it should've been fixed a long time ago. > >>>> > >>>> To make the code even simpler, try (version 6.0.2): > >>>> > >>>> In[1]:= f[]:=(Return[a];1); > >>>> > >>>> In[2]:= f[] > >>>> Out[2]= a > >>>> > >>>> It works as expected. Now try > >>>> > >>>> In[3]:= (Return[a];1)&[] > >>>> Out[3]= Return[a] > >>>> > >>>> This is obviously a bug. One would expect to see "a" if Return worked > >>>> properly, or "1" if Return didn't work inside Function, but only in > >>>> definitions such as f[]:=... above. > >>>> > >>>> I get a similar result using RuleDelayed as in > >>>> > >>>> In[4]:= 2/. 2:>(Return[a];1) > >>>> Out[4]= Return[a] > >>>> > >>>> The documentation is also contradictory. In the description of Return, > >>>> there's an example that shows that Return exists only the innermost > >>>> loop (construct) such as Do. Much like Break[], why isn't there Break > >>>> [expr] instead? But in tutorial/LoopsAndControlStructures they say: > >>>> Return[expr] return the value expr, exiting all procedures and > >>>> loops > >>>> in a function > >>>> > >>>> Best, > >>>> Norbert > >>>> > >>>> > >>>> > >>> > >>> > >> > >> -- > >> DrMajorBob at yahoo.com > >> > > > -- > DrMajorBob at yahoo.com > >