Copyright (C) 1997 Rich Neidinger, John Swallow, and Todd Will.  Free for
distribution to college and university instructors for personal,
non-commercial use.  If these notebooks are used in a course, the authors
request $20 per student.

10. Anonymous Functions

Last revision:  November 15 1996

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.

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

Since anonymous functions have no name, we don't, in fact, declare or
define them.  Instead, we "express" them.  To express an anonymous
function, think of it in its normal "defined" form and replace every
occurrence of the name of the parameter with "#" (if there's only one
parameter), or replace every occurrence of the first named parameter by
"#1", every occurrence of the second named parameter by "#2", and so on.
Then eliminate the left-hand side of the colon-equals sign and the
colon-equals symbol itself, enclose the remaining expression in parentheses
(to be safe), and append the "anonymous function operator" "&" to the
expression.

For example, let's look at how we might convert the our squaring function
into an anonymous function.  Here's the squaring function, as defined
before:

square[x_] := x^2;

We note that there is only one parameter.  Hence we replace every
occurrence of "x" by "#", to get "square[#_] := #^2"; then we eliminate the
colon-equals sign and all that precedes it, to get "#^2"; then we enclose
the expression in parentheses and append a "&", resulting in

(#^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[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}]".  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[ ]".