Message Boards Message Boards

0
|
10075 Views
|
8 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Return[] in functions

Posted 11 years ago

Hello,

in this example of code:

f1[x_] := Return[x + 1];

f2 := Function[{x}, Return[x + 1]];

f1[1] returns "2", but f2[2] returns "Return[2]". Why doesn't the Return[] operator work correctly in the second function?

POSTED BY: Pavel AZ
8 Replies
Posted 11 years ago

OK, so these two ways of functions declaration aren't equivalent.

This is exactly true: these are completely different constructs. Strictly speaking, there are no "function declarations" in Mathematica (in the C language sense). Mathematica has global replacement rules and pure functions.

When you evaluate

f[x_]:=x^2

you define a global replacement rule which replaces each occurrence of an expression which matches f[x_] with x^2.

When you evaluate

f=#^2&

or

f=Function[x,x^2]

you define a global replacement rule which replaces each occurrence of f with Function[#,#^2] or Function[x,x^2] accordingly. The Function has its own logic of evaluation.

POSTED BY: Alexey Popkov

Ah yes, code that takes code in its argument. One might like to think that things like that are exceptional cases, but that isn't necessarily so for many of the things one might want to do with Mathematica. So this sort of thing is very worth remembering when one finds behavior that seems "buggy" in code that one has written that processes code--and such cases will invariably have Hold* attributes or make use of Unevaluated and things like that....

POSTED BY: David Reiss

Well, that has its dangers too.

Consider this toy example:

In[5]:= SetAttributes[f, HoldAll]
f[x_] := Catch@Module[{}, If[x < 0, Throw[$Failed]]; Sqrt[x]]

In[7]:= f[-1]    
Out[7]= $Failed

In[8]:= f[2]    
Out[8]= Sqrt[2]

In[9]:= f[Throw[boo]; 2]    
Out[9]= boo

The same caveat applies to Sow/Reap.

This can be fixed by using a (private) tag with Throw and Catch (or Sow and Reap).

POSTED BY: Szabolcs Horvát

Actually I always use

f[...] :=
    Catch@Module[{...},
        ...
        If[error, Message[f::err]; Throw[$Failed]];
        ...
        If[otherError, Message[f::err]; Throw[$Failed]];
        ...
        result
     ]

in those cases ;-) . Part of the reason is just habit, but also it allows me to control exactly where the Throw gets caught without any ambiguity. And one can use tags in appropriately palced Throws and Catches if a more complex logic is needed.

POSTED BY: David Reiss

This is some useful reading: http://mathematica.stackexchange.com/q/29353/12

@David

While Return is very rarely needed, I think it's quite useful in situations like

f[...] :=
    Module[{...},
        ...
        If[error, Message[f::err]; Return[$Failed]];
        ...
        If[otherError, Message[f::err]; Return[$Failed]];
        ...
        result
     ]

(since this can be such a common pattern)

POSTED BY: Szabolcs Horvát

And a more general statement is never to use Return anywhere in your Mathematica programs. (Nor use Label, Goto, or other ancient approaches to flow control--they are in Mathematica for those who are coming from old programming paradigms, but are strongly recommended against.) If you need to leave a program flow prematurely use Throw and Catch or in some cases Sow and Reap. Remember that Mathematica returns the last evaluation in a CompoundExpression (i.e., a sequence of commands separated by semicolons) so long as the final command is not ended with a semicolon.

POSTED BY: David Reiss
Posted 11 years ago

OK, so these two ways of functions declaration aren't equivalent.

POSTED BY: Pavel AZ
Posted 11 years ago

Actually f2[2] returns "Return[3]". Don't use "Return" in a pure function, write

f2 := Function[{x}, x + 1];

Now f2[2] returns 3.

POSTED BY: Douglas Kubler
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract