As we’ve seen in this book, there’s a huge amount that can be done with functions that are already built into the Wolfram Language. But you can go even further if you define your own functions too. And the Wolfram Language has a very flexible way of letting you do this.

Let’s start with a typical, simple example of a function definition.

pinks[n_]:=Table[Pink,n]

pinks[5]

pinks[10]

How does this function definition work? The idea is that the := defines a value for the pattern pinks[n_]. When you ask for pinks[5], this matches the pinks[n_] pattern, and the value you’ve defined for this is used.

But this is just the beginning of the story of function definition in the Wolfram Language. Because in the Wolfram Language, you can give a definition for anything.

{f[Red],f[Yellow],f[Green],f[Orange],f[Magenta]}

f[Red]=1000;f[Green]=2000;

{f[Red],f[Yellow],f[Green],f[Orange],f[Blue]}

Now let’s add a definition for the pattern f[x_]. The Wolfram Language will use this whenever the special definitions for f[Red] and f[Green] don’t apply.

f[x_]:=Framed[Column[{x,ColorNegate[x]}]]

{f[Red],f[Yellow],f[Green],f[Orange],f[Blue]}

Clear[f]

As another example, let’s do the classic computer science exercise of defining the factorial function. Start by saying that factorial[1]=1. Then define how to compute factorial[n_] recursively in terms of another instance of factorial.

factorial[1]=1; factorial[n_Integer]:=n*factorial[n-1]

factorial[50]

50!

Instead of having definitions for factorial[1] and factorial[n_] we could have had a single definition and used If. But having separate definitions for each case tends to make things much easier to read and understand.

factorial[n_Integer]:=If[n==1,1,n*factorial[n-1]]

It’s nice to be able to break out special cases, but the real power of being able to make definitions for anything comes when one goes beyond simple function[arguments] cases.

As a simple example, consider making a definition for plusminus[{x_,y_}].

plusminus[{x_,y_}]:={x+y,x-y}

plusminus[{4,1}]

plusminus[v_]:={v[[1]]+v[[2]],v[[1]]-v[[2]]}

It’s very common to want to define a function that applies only to objects with a certain structure. This is easy to do with patterns. Here’s an example.

{a,Framed[b],c,Framed[{d,e}],100}

highlight[Framed[x_]]:=Style[Labeled[x,"+"],20,Background->LightYellow]

highlight/@{a,Framed[b],c,Framed[{10,20}],100}

highlight[list_List]:=highlight/@list

highlight[{a,Framed[b],c,Framed[{10,20}],100}]

highlight[x_]:=Style[Rotate[x,-30Degree],20,Orange]

highlight[{a,Framed[b],c,Framed[{10,20}],100}]

Define a function f that computes the square of its argument. »

Define a function poly that takes an integer, and makes a picture of an orange regular polygon with that number of sides. »

Define a function f that takes a list of two elements and puts them in reverse order. »

Create a function f that takes two arguments and gives the result of multiplying them and dividing by their sum. »

Define a function f that takes a list of two elements and returns a list of their sum, difference and ratio. »

Define a function evenodd that gives Black if its argument is even and White otherwise, but gives Red if its argument is 0. »

Define a function f of three arguments where the second two arguments are added if the first argument is 1, multiplied if it’s 2 and raised to a power if it’s 3. »

Define a Fibonacci function f with f[0] and f[1] both being 1, and f[n] for integer n being the sum of f[n-1] and f[n-2]. »

Create a function animal that takes a string, and gives a picture of an animal with that name. »

Define a function nearwords that takes a string and an integer n, and gives the n words in WordList[ ] that are nearest to a given string. »

What kind of a pattern can be used in a function definition?

Absolutely any pattern you want. Even one where the head is itself a pattern.

How can I see the definitions made for a particular function?

Use ?f to see the definitions for f.

How do I overwrite an existing function definition?

Just make a new definition for the same pattern. Use Clear to remove all definitions.

How are different definitions for a particular function sorted?

Typically from most specific to least specific. If there are definitions that can’t be ordered by specificity, definitions made later are put later. When definitions are used, the earlier ones are tried first. ?f shows the ordering of definitions for f.

Can I redefine built-in functions like Max or Plus?

Usually yes. First, though, you often have to say e.g. Unprotect[Max]. Then definitions you add will be used in preference to built-in ones. Some functions, like Plus, are so fundamental that the system locks them in a protected state. Even in this case, though, you can make “upvalue” definitions that are associated with particular structures of arguments.

Can I do object-oriented programming in the Wolfram Language?

A symbolic generalization of object-oriented programming, yes. Given an object “type” t, one wants to make definitions e.g. for f[t[...]] and g[t[...]]. One can associate such definitions with t by saying t/:f[t[...]]=... In the Wolfram Language, this is called defining an upvalue for t.

Can I use = instead of := for function definitions?

Sometimes. f[n_]=n^2 will work fine, because the right-hand side doesn’t evaluate when you make the assignment. f[n_]=Now and f[n_]:=Now will give different results. And in many cases the right-hand side can’t be meaningfully evaluated until specific arguments are given.

How can I share function definitions with other people?

Just send the code! A convenient way to do this through the cloud is to use CloudSave and CloudGet, as discussed in Section 43.

Tech Notes