Re: Re: Re: Return in function

*To*: mathgroup at smc.vnet.net*Subject*: [mg106110] Re: [mg106045] Re: [mg106018] Re: Return in function*From*: DrMajorBob <btreat1 at austin.rr.com>*Date*: Fri, 1 Jan 2010 05:38:40 -0500 (EST)*References*: <hftbe9$cjh$1@smc.vnet.net> <200912300915.EAA17319@smc.vnet.net>*Reply-to*: drmajorbob at yahoo.com

> 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