MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Re: Return in function

  • To: mathgroup at smc.vnet.net
  • Subject: [mg106107] Re: [mg106045] Re: [mg106018] Re: Return in function
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Fri, 1 Jan 2010 05:38:06 -0500 (EST)
  • References: <hftbe9$cjh$1@smc.vnet.net> <200912300915.EAA17319@smc.vnet.net>

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
>


  • Prev by Date: Re: Re: Replace and ReplaceAll -- simple application
  • Next by Date: Re: Re: Re: Return in function
  • Previous by thread: Re: Re: Re: Return in function
  • Next by thread: Re: Re: Re: Return in function