MathGroup Archive 1999

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

Search the Archive

RE: "f[x_]:= 2 x" vs. "f = 2 #&"

  • To: mathgroup at smc.vnet.net
  • Subject: [mg16467] RE: [mg16365] "f[x_]:= 2 x" vs. "f = 2 #&"
  • From: "Ersek, Ted R" <ErsekTR at navair.navy.mil>
  • Date: Sat, 13 Mar 1999 02:22:03 -0500
  • Sender: owner-wri-mathgroup at wolfram.com

Kevin Jaffe wrote:
-------------------------
What significant differences exist among the following
three ways to define a function f:

  f[x_]:= 2 x

  f = Function[x, 2 x]

  f = 2 #&

Are there situations where one form is better than the others?
--------------------------

Since you name each function (f) there is little difference except possibly
timing performance, but there can be other factors involved for pure
functions that aren't named.  Consider the lines below.

In[1]:=
f[x_]:=2 x

Using the convention above we can map (f) over a list with the next line.
Using this approach we have to use a variable for the name of the function.
In[2]:=
Map[f,{a,b,c}]
Out[2]=
{2 a,2 b,2 c}

We can use a pure function to do the same thing in the next line.  This has
the advantage that we don't have to use a variable to name the function.  It
also has the advantage that it's very concise.  One disadvantage is that it
looks like Greek to a newbee.
In[3]:=
Map[2#&,{a,b,c}]
Out[3]=
{2 a,2 b,2 c}

The FullForm of (2#&) is more or less
  Function[2#]

This almost the same as 
  Function[x, 2x]

-------------------------------
Suppose you are writing a program with the form
  func[x_]:= (*****algorithm*****)
and (algorithm) has to make a function that will be used at later stages of
(algorithm).

It's illegal to use patterns on the right side of a definition.
So (algorithm) can't make the function with the approach
  f[x_]:= 2 x
It also can't make the function with the approach
  f[x_]= 2 x
Instead (algorithm) must make the function with one of the following
  f=2#&
  f=Function[2#]
  f=Function[x,2x]

So when would you need to do this?
One such case is the function below.  This function will plot a function
using arbitrary precision arithmetic to sample the function.  This is useful
in special cases when a function must be sampled using arbitrary precision
arithmetic.

(***********)
PrecisionPlot[f_,{x_,xmin_,xmax_},opts___?OptionQ]:=
 Module[{g,h},
  (g=Function[f/.x->#];
     h=(g[SetPrecision[#,17]]&);
     Plot[h[x],{x,xmin,xmax},opts]
   )
 ]
(***********)

As far as I can tell there was no way to get PrecisionPlot working without
using a pure function as I do with   g=Function[f/.x->#]

For an extensive discussion of this program down load (PrecisionPlot.nb) at
http://www.mathsource.com/Content/Enhancements/Graphics/2D/0209-887

This is a brand new MathSource item I submitted.

--------------------
Now suppose you need to define a function with the attributes Flat,
Orderless.
You could use the approach:
  SetAttributes[f,{Flat,Orderless}];
  f[x__]:=  (*****expr******)

Now what if you want to avoid giving this function a name, or if you
absolutely had to use pure function as I did with PrecisionPlot.  
In this case you can't use the short hand notation ( as in 2#& ). 
Instead you can use the following
  Function[##,  (*****expr*****), {Flat,Orderless} ]

Note, ## stands for all arguments given to the function.

As a concrete example where this can be used Dave Withoff once helped me
debug some code that will force StandardForm to use the equivalent of
MatrixForm to format a matrices.  The code is given below.

(*********************)
MakeBoxes[m_?(Function[t, MatrixQ[Unevaluated[t]]&&(  t=!={{}}   ),
 HoldAll]), form_]:=
 RowBox[{"(",
   GridBox[
      Map[Function[t, MakeBoxes[t, form], HoldAll],
      Unevaluated[m],{2}]],
  ")"}]
(*****************)

Notice the part that says;
  Function[t, MakeBoxes[t, form], HoldAll]
This is a function that wasn't given a name.

Apparently you don't have to have the attributes in a list if there is only
one of them.  However, this isn't indicated in the documentation.

--------------------------
Section 2.6.4 of the Mathematica Book covers some advanced aspects of
variable scoping inside Function.  I don't think the points discussed in
this section apply to constructs like 
( f[x_]:=2x  )
However, I still need to get a good handle on that section of the book.

If you paste the line below into a notebook you will have a hyperlink to
section 2.6.4.
(*****************)
\!\(\*
  ButtonBox[\(2.6  .4\),
    ButtonStyle->"MainBookLink"]\)
(*****************)

--------------------------

I did some timing tests for the different ways of defining functions, and
the results were very interesting.  I used ($HistoryLength=0) so memory used
wouldn't increase.  I also did it with a new list each time so the kernel
couldn't get the results out of the cache table.

In[1]:=
$HistoryLength=0;
lst=Table[Random[],{4  10^4}];

In[2]:=
Map[2#&,lst];//Timing
Out[2]=
{3.24 Second,Null}


In[3]:=
f[x_]:=2x
lst=Table[Random[],{4  10^4}];

In[4]:=
Map[f,lst];//Timing
Out[4]=
{5.71 Second,Null}


In[5]:=
lst=Table[Random[],{4  10^4}];

In[6]:=
Map[Function[x,2x],lst];//Timing
Out[6]=
{6.31 Second,Null}

However, the results above would vary slightly when repeated.  This may be
because I am using Windows 95.  I once heard something about how the Win 95
OS makes it impossible for Timing to give an accurate result.

If anyone has questions, just ask.

Regards,
Ted Ersek


  • Prev by Date: Re: estimating parameters for diffeq model
  • Next by Date: importing data
  • Previous by thread: "f[x_]:= 2 x" vs. "f = 2 #&"
  • Next by thread: Re: RE: "f[x_]:= 2 x" vs. "f = 2 #&"