10. Anonymous Functions

Last revision: February 9 1998

In this section we introduce anonymous functions, explore their similarity to inline functions in compiled languages, and show how anonymous functions can simplify code for certain operations.

Mathematica operations/structures introduced: 
     anonymous functions; Function, #,  &
     First[]
     Last[]
     Select[]
     NumberQ[], IntegerQ[], EvenQ[], OddQ[], PrimeQ[]

Anonymous Functions

In the previous section we considered defining functions using Modules and the colon-equals (SetDelayed) operator ":=".  When we did so, we gave the new function and each of its parameters a name.  This form might be called the procedural form, or long form, of a function definition.  Mathematica provides another form which eliminates the need to name the function or its parameters; instead, the expression itself, without names, "is" the function definition, hence the term "anonymous function".

Why would we want to use expressions which represent functions instead of simply defining them with names?  There are several reasons.  First, we may only need to use the function one particular time, in which case we need not name it to use it again.  Second, the representations of anonymous functions provide a simple shortcut to defining functions, and while some anonymous functions are extremely difficult to read, the simpler ones are just as easy to read as the equivalent named functions defined using colon-equals.  Finally, we introduce "anonymous functions" because they have a cousin in many compiled languages, which we describe as follows.

Inline functions

Computers do not actually execute the source code written in any language; in one way or another, the source code must be converted into machine code---the only code the computer understands---and then executed.  In interpreted languages such as Mathematica, this conversion happens "on-the-fly" in the sense that only when we ask to execute a cell (and every time we ask to execute a cell) is the code converted. In contrast, for compiled languages such as C, Fortran, or Pascal, the source code is passed through a compiler which performs the conversion, leaving the final machine code in a file which can be executed repeatedly without reconversion.

During the compilation process, the compiler of a standard computer language reads the source code several times, collecting the names of variables, assigning them storage locations, checking for errors, and so on. Typically one "pass" over the source code is devoted to expanding out so-called "inline functions", and these are cousins to Mathematica's "anonymous functions". Let's examine the difference between the way an inline function and a normal function is embedded in machine code by looking at how a compiler might convert some Mathematica code into a machine language.  (Of course, this machine language is intended to be representative only; no computer exists which executes these machine instructions.)

Suppose the code is the following:

f[x_] := x^2 + x + 5; a = f[10]+f[20]+f[30];

If f[] were not declared inline, then the machine code might look like this:

(1) Copy "10" to "x" inside function "f"
(2) Go to function "f" (step 13), execute its instructions, and return
(3) Copy result of function "f" to temporary variable "t"
(4) Copy "20" to "x" inside function "f"
(5) Go to function "f" (step 13), execute its instructions, and return
(6) Copy result of function "f" to temporary variable "u"
(7) Copy "30" to "x" inside function "f"
(8) Go to function "f" (step 13), execute its instructions and return
(9) Copy result of function "f" to variable "a"
(10) Add "a" and "u" and store the result in "a"
(11) Add "a" and "t" and store the result in "a"
(12) Stop
(13) [Beginning of function "f"] Square "x" and store in temporary variable "v"
(14) Add "v" and "x" and store the result in temporary variable "v"
(15) Add "v" and "5" and store the result in our result variable "result"
(16) Return to original ("calling") instruction

Note that the main code (steps 1--12) jumps down to step 13 three separate times to execute the function, and that  each of these times it copies beforehand a value into the variable x of the function and, after the function executes, copies the result of f back to a variable.  These jumps, together with the copy operations before and after the jumps, are called function calls.

Now suppose f[] were declared inline.  Then the machine code might instead look like this:

(1) Square "10" and store value in temporary variable "t"
(2) Add "t" and "10" and store the result in "t"
(3) Add "t" and "5" and store the result in "t"
(4) Square "20" and store value in temporary variable "u"
(5) Add "u" and "20" and store the result in "u"
(6) Add "u" and "5" and store the result in "u"
(7) Square "30" and store value in temporary variable "v"
(8) Add "v" and "30" and store the result in "v"
(9) Add "v" and "5" and store the result in "v"
(10) Add "u" and "v" and store the result in "a"
(11) Add "t" and "a" and store the result in "a"
(13) Stop

Here we find instead no function calls; instead the instructions of the function are embedded in the main code, one set (1-3, 4-6, 7-9) for each reference (f[10], f[20], f[30]) of the function.

What tradeoffs are present in the choice to use inline or normal functions?  First and foremost, programs using inline functions execute faster.  This increase in speed is due to the fact that the program does not have to spend time copying values back and forth between the main code and the function's own separate variables.  The drawback is that inline functions frequently require more lines of code---more memory devoted to the program itself.  We do not see this drawback in the case above, since the function itself needed only a few instructions, but suppose the function needed 200 machine instructions to accomplish its task and let's count how many machine instructions would be necessary to cover each of the three references to the function.  We would need a few instructions---a few copies, and the jump instruction---for each reference of the function, together with one instance of all of the instructions for the function, placed at the end.  At three instructions per function call, plus 200 instructions for the function at the end, we find we need 209 instructions.  However, with inline functions, each of the 200 instructions would need to appear inside the main code every time the function were referenced, yielding fully 600 instructions devoted to the function references.  Thus we have a tradeoff between speed of execution of the program and memory requirements for the program.

To summarize, an inline function is a function which is not implemented in the standard fashion, using one set of instructions for the function, together with one function call for each reference.  Instead, when the compiler finds an inline function referenced in the source code, it immediately inserts the instructions of the function into the program itself---hence the term "inline"---and does not insert a "function call".

Syntax of Anonymous Functions

Consider the square function which returns the square of its argument.

Clear[square];
square[x_] := x^2;

Map[ square, {1,2,3,4,5} ]

Basically, square is a function of one argument (x)which returns the square of that argument ((x^2)).  We could more literally translate this prose definition of square into Mathematica as follows.

Clear[square];
square = Function[ {x}, x^2 ];

Map[ square, {1,2,3,4,5} ]

That is, we assign to square a Function object which performs the appropriate calculation.  This Function object is an entity in its own right, for it must have been constructed before it was assigned to the variable square.  As such, we might have used it without giving it a name.  For example,

Map[ Function[ {x}, x^2 ], {1,2,3,4,5} ]

The expression "Function[ {x}, x^2 ]" is an example of an anonymous function.  An anonymous functions has no name, it's just "the function that …."  The general form for this is Function[parameter-list, body].

There is another, more succinct, notation for anonymous functions.  In this notation, the named parameter(s) are replaced by "slot(s)"—place holders for parameters.  To convert a Function to this notation, extract the body of the Function and replace every occurrence of the name of the parameter with the symbol "#" (if there are more than one parameter, replace occurrences of the first parameter by the symbol "#1", occurrences of the second parameter by the symbol "#2", etc.).  Finally, wrap the modified Function body inside parentheses (to be safe) and append the "anonymous function operator," &, to the expression.

Applying this technique to the anonymous squaring function, Function[ {x}, x^2 ], produces:

(#^2)&

Map[ (#^2)&, {1,2,3,4,5} ]

Check out the FullForm of this expression, and you'll see it is an abbreviation, of sorts, for a Function expression.

FullForm[(#^2)&]

Yes, the anonymous function is somewhat harder to read.  For an example of a case where using an anonymous function simplifies code, consider the following situation.  We wish to iterate the function Exp[-x] over and over again beginning with the value 1.  One solution is the following:

newExp[x_] := Exp[-x];
Nest[newExp,1.,100]

It is irritating that we have to go to the trouble of defining a separate function in order to use such a simple operation.   The anonymous function solution is much simpler:

Nest[Function[{x}, Exp[-x]],1.,100]

Or,

Nest[Exp[-#]&,1.,100]

(Note we didn't need the parentheses this time.)

What follows are several examples of bottom-up programming, coupled with a judicious use of anonymous functions.

Example 1: Replication

By now you should appreciate the idea of building up a function slowly, starting with the simple things and gradually adding more layers.  Let's try that idea again now.  We want to write a function called replicate[] which should take a list of integers and return a list where each number n (in the list) has been replicated n times.  For example, replicate[{3,2,4,2}] should return {3,3,3,2,2,4,4,4,4,2,2}.  As a first simple step, how can we replicate a single number, say 3? We'll begin with the following:

Clear[f]
f[n_]:=Table[n,{n}]
f[3]

Now we want to replicate each number in the list {3,2,4,2}, so we'll map f onto the list.

Map[f,{3,2,4,2}]

Now all we need to do is use Flatten[] on this list.

(It always helps to remember that,  when trying to write a new function in Mathematica, we should do three things:  (1) clear any old definition; (2) make the new definition; and (3) test the new definition.)

Clear[replicate]
replicate[list_]:=Flatten[ Map[f,list] ]
replicate[{3,2,4,2}]

One problem with our replicate[] function is that it relies on the function f[] which we defined earlier.  By now you've probably experienced the problem of trying to execute a function that relied on something you'd not yet defined.  (Imagine trying to find roster[[4]] without having first executed roster={....}. )  But even if we do remember to define f[], before trying replicate[], we have to remember not to redefine f as something else in a different problem.  For example, if the next problem in this lab asked us to plot f(x)=x+Sin[x] we might casually enter:

Clear[f]
f[x_]= x+Sin[x]
Plot[f[x],{x,-2Pi,2Pi}]

Now replicate[] will still run, but it will not run correctly.

replicate[{3,2,4,2}]

Clearly using f[] in the definition for replicate[] is a very dangerous method.  We now know two solutions to this problem:  (1) use a Module: create a function f[] inside a Module that only the function replicate[] knows about, and (2) use an anonymous function: use the function f[] without ever giving it a name.

Module Solution

Clear[replicate,f]

replicate[list_]:= 
  Module[{f},
	   f[n_]:=Table[n,{n}];
	   Flatten[ Map[f, list] ]
	 ]

replicate[{1,2,3}]

One advantage of the Module[] command is that the function f is defined in the same place as replicate[], so we don't have to worry about forgetting to execute the definition for f[] before using replicate[].  The great advantage of using Module, however, is that our definition of f[] doesn't show up outside of the replicate[] function.  Let's check.

?f

We can now use f[] elsewhere, as in

f[x_]= x+Sin[x]

and replicate[] still works just fine.

replicate[{3,2}]

Anonymous Function Solution

We want to replace the f[] we defined up above with an anonymous function.  Recall that we had defined f[n_]:=Table[ n, {n}].

Using Function, this converts to Function[{n}, Table[ n, {n}] ].

Function[{n}, Table[n,{n}]] [3]

Alternatively, following our rules for converting the definition into an expression with no named parameters, we get  Table[ #, {#}].  So the anonymous function is Table[ #,{#}]& or, more safely,  (Table[ #,{#}])&.

Table[#,{#}]& [3]

Note that the 3 gets substituted into each of the #'s, and the resulting Table[3,{3}] is executed.  Now we can map this anonymous function onto a list just as we did the named function f[].

Clear[replicate]
replicate[list_]:=
		Flatten[ Map[ Table[#,{#}]&, list] ]
replicate[{1,2,3}]

Using an anonymous function gave us a shorter segment of code than using a Module, and this segment will also run a little bit faster. To see this, let's time how long it takes for each to run 10 times:

Clear[replicate1,replicate2]

replicate1[list_]:= 
  Module[{f},
	   f[n_]:=Table[n,{n}];
	   Flatten[ Map[f, list] ]
	 ];
replicate2[list_]:=
		Flatten[ Map[ Table[#,{#}]&, list] ];

Timing[Do[replicate1[{1,2,3}],{10}]]

Timing[Do[replicate2[{1,2,3}],{10}]]

Example 2: Selecting some {x,y} pairs (First, Last, Select)

The following code gives a framed plot of 50 random points in the unit square in the first quadrant.

pairs=Table[{Random[],Random[]},{50}];
ListPlot[pairs,
	 Frame->True,
	 AspectRatio->Automatic,
	 PlotRange->{{0,1},{0,1}}];

We would like to write a function aboveLine[] that will select from the points above those that are above the line y = x.  In other words, we would like to decide, for each point, whether the y value is greater than the x value---this is what "above the line" means mathematically---and then choose only those points from the first random list.  We'll use some functions First[] and Last[] which operate on lists as might be expected:

aboveLineOne[point_]:= Last[point]>First[point]

aboveLineOne[{.2,.4}]

aboveLineOne[{.6,.2}]

It looks as if we've solved the problem of deciding whether a point is above the line y=x, but rather than defining the function out in the open, let's place this function inside a Module.  Clear the current definition of aboveLineOne[] before starting.

Clear[aboveLineOne]

Module Solution

We will use the Select[] function.  Select[] takes two arguments, the first a list from which we want to extract certain elements, the second a function which, for each element of the list, will give a True or False answer to whether we want the element.

Clear[aboveLine]

aboveLine[points_]:=
  Module[{aboveLineOne},
	   aboveLineOne[point_]:=
	      Last[point]>First[point];
	   Select[points, aboveLineOne]
	 ]

abovePts=aboveLine[pairs];

Let's plot these points and see whether our code is correct.

ListPlot[abovePts,
	 Frame->True,
	 PlotRange->{{0,1},{0,1}},
	 Axes->None,
	 AspectRatio->Automatic];

All the points do seem to be above y = x.

Anonymous Function Solution

We want an anonymous version of the function: 
	aboveLineOne[point_] := Last[point] > First[point]
Now point is the only parameter, so we use "#" in place of it, which yields an expressed anonymous function (Last[#]>First[#])&.  Let's try it out:

(Last[#]>First[#])& [{3,4}]

Now we use the function to select the points above the line.

Clear[aboveLine]
aboveLine[points_]:=
	 Select[ points, (Last[#]>First[#])& ]
abovePts=aboveLine[pairs];

ListPlot[abovePts,
	 Frame->True,
	 PlotRange->{{0,1},{0,1}},
	 Axes->None,
	 AspectRatio->Automatic];

Example 3: Selecting multiples of k from a list (Q functions)

Suppose that we want to know which of the following integers are multiples of some integer we specify, such as, say, 3.

numbers={23,5,3,345,67,345,245,4,2,2,5,36,3,42,2,436}

How do we know if an Integer is a multiple of another Integer?  We might ask a simpler question:  how do we know if a value is an Integer?  Can we ask Mathematica?  Yes.  There are boolean functions NumberQ, IntegerQ, EvenQ, OddQ, and even PrimeQ, which simply return True or False depending on the value of the argument.  The "Q" in the names is a shorthand for the word "Query".  Let's try a few:

IntegerQ[3.5]

NumberQ[2/3]

OddQ[2]

PrimeQ[373587883]

We return to our original question in light of these boolean functions.  To know whether or not one Integer is a multiple of another, we divide and ask whether the result is an Integer.

Module Solution

We incorporate multK[] into the definition of multiples[], using the value of k which is an argument of multiples[]:

Clear[multiples,multK]
multiples[numbers_,k_]:=
  Module[{multK},
	   multK[x_]:=IntegerQ[x/k];
	   Select[numbers, multK ]
	 ]
multiples[numbers,3]

Anonymous Function Solution

We replace multK[] with the anonymous (nameless) equivalent, IntegerQ[#/k] &:

Clear[multiples,multK]
multiples[numbers_,k_]:=
		Select[numbers,IntegerQ[#/k]&]
multiples[numbers,3]

Here the anonymous function has only one argument from elements in the list numbers; k appears as an argument to the function multiples.

Use of Anonymous Functions

The examples above suggest that anonymous functions are best employed when (a) the operation(s) to be performed are simply expressed, (b) the operations use relatively few parameters, and (c) when we need to use a function which requires, as one of its parameters, the name of a function, in which place we may place the anonymous function.  Particularly appropriate functions which take functions as parameters are Select[], Map[], and Apply[].