Function

Why use pure functions?

• If a function is used many times over it can run 15 times faster if it's implemented as a pure function.
• Programming with pure functions is often more concise.  
   For example the following line uses a pure function in Select to return all elements of data with a magnitude less than 50.

data = {-4, 34, -98, -23, 68, 31} ; Select[data, Abs[#] <50&]

{-4, 34, -23, 31}

The following line also returns all elements of data with a magnitude less than 50.  This version doesn't use pure functions. Notice the version using a pure function is more concise but seems cryptic until you get used to pure functions.

Small[x_] := Abs[x] <50 ; Select[data, Small]

{-4, 34, -23, 31}

Before looking at examples below it might help to clear definitions from all global symbols with the next cell.

ClearAll["Global`*"]

Pure functions that use only one argument

The next cell defines a function (f) which returns 3 plus it's argument.

f[x_] := 3 + x

In the next cell I give four different ways to define a pure function (g) which returns 3 plus it's first argument. The expression used to define the function varies depending which version is used, but as far as I can tell there is no meaningful difference between the different versions.
The Symbol (#) is short hand for Slot[1] and it refers to the first argument given to a pure function.

g = 3 + #& ; g = Function[3 + #] ; g = Function[x, 3 + x] ; g = Function[{x}, 3 + x] ;

In the next cell we see f[t] returns the same thing as g[t].

{f[t], g[t]}

{3 + t, 3 + t}

Functions (f) and (g) don't always do the same thing.  Function (f) is only defined when given one argument, but the pure function (g) is defined when given one or more arguments.  The pure function (g) uses the first argument and ignores all other arguments.

{f[t1, t2], g[t1, t2]}

{f[t1, t2], 3 + t1}

Pure functions that use an  n^th argument

ClearAll[f, g]

In the next cell I define a function (f) that takes three arguments.

f[x_, y_, z_] := {x - y, x - z} ; f[a, b, c]

{a - b, a - c}

In the next cell I give three ways to define a pure function that does essentially the same thing as (f) in the previous cell.  The FullForm of (#n)  is Slot[n], and we use (#2, and  #3) refer to the second and third arguments of a pure function. The third way of defining the pure function results in differnt form of storing the functions definition that the first two solutions, but as far as I can tell there is no meaningful difference between the different versions.

g = {#1 - #2, #1 - #3} & ; g = Function[{#1 - #2, #1 - #3}] ; g = Function[{x, y, z}, {x - y, x - z}] ;

g[a, b, c]

{a - b, a - c}

Notice the previous definition for (g) will complain if it's given an insufficient number of arguments.  Because of this you shouldn't use pure functions to define a function an end user will use.  However, pure functions are a good choice for private functions in a package since the end user will not be using the private functions.

g[x, y]

Function[{x, y, z}, {x - y, x - z}][x, y]

Notice it's perfectly legal for a pure function to ignore some arguments before the n^th argument.  To demonstrate this point I define (g) below which returns the sum of it's 2^nd and 4^tharguments. In this case all other arguments are ignored.

ClearAll[g, x2, x4] ; g = #2 + #4& ; g[x1, x2, x3, x4, x5, x6]

x2 + x4

Pure functions that use an arbitrary number of arguments

ClearAll[f, g]

The following cell defines a function (f) that puts all it's arguments in a list and squares each element.  The squaring operation is mapped to each element because Power has the Listable attribute, but that's another subject.

f[x__] := {x}^2 f[x, y, 5, 3/2^(1/2)]

{x^2, y^2, 25, 9/2}

In the next cell I give two ways to define a pure function that puts all its elements in a list and square each element.  The FullForm of ## is SlotSequence[1] and is used to refer to all the arguments passed to a pure function.  The two styles used here result in exactly the same definition for the function.

g = {##}^2& ; g = Function[{##}^2] ;

g[x, y, 5, 3/2^(1/2)]

{x^2, y^2, 25, 9/2}

Use of ##n

ClearAll[f, g]

The next cell defines a pure function (g) that puts all it's arguments starting with the third argument in a list and squares each element. The FullForm of  (##3)  is SlotSequence[3] and it refers to all arguments of a pure function from the third argument on.  The two styles used here result in exactly the same definition for the function.

g = {##3}^2& ; g = Function[{##3}^2] ;

g[v, x, y, 5, 3/2^(1/2)]

{y^2, 25, 9/2}

Earlier I demonstrated that Mathematica will complain if a pure function uses #3 and is given less than three arguments.  So it's curious that Mathematica doesn't complain below when (g) tries to use ##3, but is given only two arguments.

g[x, y]

{}

Pure functions with one attribute

ClearAll[f, g]

In the next cell I define a function (f) that returns True if it's argument is a Symbol before evaluating and otherwise returns False.  Programming this function is slightly tricky because evaluation is prevented in two places.  First we give (f) the HoldAll attribute to prevent it's argument from evaluating before using the definition of (f).  In addition we use Unevaluated[x] to prevent the argument (x) from evaluating before getting it's head.

Attributes[f] = {HoldAll} ; f[x_] := (Head[Unevaluated[x]] === Symbol)

In the next cell we see f[t] returns True even when (t) evaluates to a number rather than a symbol.

t = 1.4 ; {f[t], f[1.4]}

{True, False}

In the next cell I give four ways to define a pure function (f) that does essentially the same thing as (f) defined above.

g = Function[  x,   Head[Unevaluated[x]] === Symbol, HoldAll] ; g = Functi ... ated[x]] === Symbol, {HoldAll}] ; g = Function[{x}, Head[Unevaluated[x]] === Symbol, {HoldAll}] ;

In the next cell we see (g) does the same thing as (f).  I have found useful applications for this pure function.

t = 1.4 ; {g[t], g[1.4]}

{True, False}

Pure functions with multiple attributes

ClearAll[f, g]

The next cell defines a function (f) which prevents it's arguments from evaluating, puts the arguments in canonical order, converts the arguments to strings and concatenates the sorted strings with another string.

Attributes[f] = {HoldAll, Orderless} ; f[x_, y_] := (ToString @ Unevaluated @ x<>"..."<>ToString @ Unevaluated @ y) ;

In the next cell we see (f) in action.  You will find f[t,s] returns the same thing as f[s,t].

s = 6 ; t = 9 ; f[t, s]

s...t

The next cell defines a pure function (g) that does essentially the same thing as (f) above.

g = Function[{x, y}, ToString @ Unevaluated @ x<>"..."<>ToString @ Unevaluated @ y, {HoldAll, Orderless}] ;

In the next cell we see (g) in action.

s = 6 ; t = 9 ; g[t, s]

s...t

Pure functions that use no arguments

ClearAll[f1, f2, x] ;

(h&) is a pure function with no arguments which always returns (h). An occasion where this is needed is in the PolygonTessellation package available at http://library.wolfram.com/packages/. This package includes a function called TessellatePolygon3D with a WindingRule option. The WindingRule setting should be a function that returns True or False. A typical setting of this option is WindingRule→OddQ, but in some cases you want a test that always comes out True. In that case the setting WindingRule→(True &) should be used.

Often times the ButtonFunction for buttons is a pure function with no arguments.  I give such an example in my section on ButtonProgramming.

Consider f1, f2 in the next cell. Here the function f1 returns True no matter what argument(s) it has, and f2 returns a random number between 0 and 1 no matter what argument(s) it has.

f1 = True& ; f2 = Random[] & ; {f1[x], f1[24.5], f1[4], f1[1, 2, 3], f2[x], f2[10^7], f2[1, 2, 3]}

{True, True, True, True, 0.89133, 0.193043, 0.735216}

Keep in mind (f1) isn't True it's a function that always returns True and that explains why the first element of the next list is False.

{f1 === True, f1[] === True, f1[x] === True}

{False, True, True}

Use of  #0  (rarely useful)

ClearAll[f] ;

When used in a pure function (#0) represents the pure function itself.  I can't imagine when this would be useful, but I demonstrate it in with the pure function (f) in the next cell.  This pure function prints (The second argument is ...) and returns the entire pure function as an expression.

f = ((Print["The second argument = "<>ToString[#2]] ; #0) &) ;

In the next cell we see (f) in action.

f[wx1, wx2, wx3, wx4]

The second argument = wx2

(Print[The second argument = <>ToString[#2]] ; #0) &

Also read  "Further Examples" at the end of the  Function  documentation in the Help Browser.


Created by Mathematica  (May 16, 2004)

Back to Ted’s Tricks index page