Search
Functional Programming
Untitled (the Wolfram Language for Students - Personal Use Only : www.wolfram.com)

Defining functions

Functions are just another type of expression in Mathematica

Their argument lists take the form of patterns. We will discuss patterns in more depth in the next lecture

For now, we will make use of one kind of pattern: x_
which matches any expression and calls it x.
For example:

Functional_Programming_1.png

This function can be called with any kind of argument. That argument will be called x in the body of the function, which gives a result by adding one

Functional_Programming_2.png

Functional_Programming_3.png

Functional_Programming_4.png

Functional_Programming_5.png

There are much more sophisticated patterns than just “match any expression.” We will cover these later.

Suppose we want to recursively compute the factorial
Base case: fac(0) = 1
Recursive definition: fac(n) = n*fac(n-1)

This is simple to define in Mathematica.
We begin with the base case

Functional_Programming_6.png

Now, fac[0] will evaluate to 1

Functional_Programming_7.png

Functional_Programming_8.png

We don’t have a rule for the general case, so fac[n] will remain unevaluated:

Functional_Programming_9.png

Functional_Programming_10.png

Defining the general case:

Functional_Programming_11.png

Functional_Programming_12.png

Functional_Programming_13.png

Functional_Programming_14.png

Functional_Programming_15.png

Functional_Programming_16.png

Functional_Programming_17.png

Let’s do a similar exercise with the Fibonacci sequence:
Functional_Programming_18.gif

Functional_Programming_19.gif

Functional_Programming_20.png

Functional_Programming_21.png

Of course, Mathematica also has this built in, so we can check our work...

Functional_Programming_22.png

Functional_Programming_23.png

Solving recurrence relations

Suppose we have the recurrence relation

Functional_Programming_24.png

We can easily create a function to recursively evaluate this sequence

Functional_Programming_25.gif

Functional_Programming_26.png

Functional_Programming_27.png

What if we want to know a general (non-recursive formula)?
First, concentrate on the recursive definition Functional_Programming_28.png (ignoring boundary conditions)
We can solve this recurrence by making the ansatz that Functional_Programming_29.pngis given by Functional_Programming_30.png for some r
In that case,

Functional_Programming_31.png

So, we look for solutions to this equation.

Functional_Programming_32.png

Functional_Programming_33.png

So, r=5 and r=2 satisfy this relationship.
The general solution will be given by Functional_Programming_34.png

We can easily solve the system of equations to find the values of c and d.
But we can also let Mathematica help...

Functional_Programming_35.gif

Functional_Programming_36.png

Functional_Programming_37.png

Functional_Programming_38.png

Functional_Programming_39.png

Functional_Programming_40.png

Let’s check our formula

Functional_Programming_41.png

Functional_Programming_42.png

Functional_Programming_43.png

Functional_Programming_44.png

ClearAll deletes all the definitions we made for a

Functional_Programming_45.png

Mathematica can also solve the recurrence directly using RSolve

Functional_Programming_46.png

Functional_Programming_47.png

More complicated functions and local variables

Sometimes we want to introduce local variables in a function for intermediate values in long calculations

This can be achieved using Module

Functional_Programming_48.png

Functional_Programming_49.png

Functional_Programming_50.png

Functional_Programming_51.png

Functional_Programming_52.png

Functional_Programming_53.png

Mathematica also has other scoping mechanisms (i.e. for creating variables with local scope)
See e.g. Block, With

For our uses, Module is sufficient

Functional style programming

Mathematica is a multi-paradigm programming language

It supports both functional and imperative programming, but functional constructs are often very natural

For example, applying a function f to a list is known as mapping f over the list

Functional_Programming_54.png

Functional_Programming_55.png

Functional_Programming_56.png

Functional_Programming_57.png

Map is considered so important in Mathematica it has its own syntax

Functional_Programming_58.png

Functional_Programming_59.png

We can define more complicated functions if we want

Functional_Programming_60.png

Functional_Programming_61.png

Functional_Programming_62.png

Sometimes we want to create an anonymous function so that we don’t need to name it

Functional_Programming_63.png

Functional_Programming_64.png

Here # indicates the argument, and & tells Mathematica that the preceding expression is a function

This notation can easily become hard to read, so be careful

Functional_Programming_65.png

Functional_Programming_66.png

More functional programming

Recall our list

Functional_Programming_67.png

Functional_Programming_68.png

We can apply filters to the list using Select

Functional_Programming_69.png

Functional_Programming_70.png

We can combine this with anonymous functions

Functional_Programming_71.png

Functional_Programming_72.png

Sometimes we want to apply a function to a list for its side-effect rather than its return-value

For this we have Scan

Functional_Programming_73.png

Functional_Programming_74.png

Functional_Programming_75.png

Functional_Programming_76.png

Functional_Programming_77.png

Functional_Programming_78.png

Functional_Programming_79.png

Functional_Programming_80.png

Functional_Programming_81.png

Functional_Programming_82.png

Functional_Programming_83.png

There are a ton more functional programming facilities in Mathematica

See e.g. Nest, Fold, Apply

Functional_Programming_84.png

Functional_Programming_85.png

Can we get the sum of all of these entries?

Functional_Programming_86.png

Functional_Programming_87.png

Functional_Programming_88.png

Functional_Programming_89.png

Functional_Programming_90.png

Functional_Programming_91.png

Functional_Programming_92.png

Functional_Programming_93.png

Functional_Programming_94.png

Functional_Programming_95.png

Patterns

We have seen one type of pattern before: x_

The underscore will match any expression, and then the result will be called x

We can test if a pattern matches an expression using MatchQ

Functional_Programming_96.png

Functional_Programming_97.png

Functional_Programming_98.png

Functional_Programming_99.png

There are other kinds of patterns.

Except will match anything except what’s in the brackets

Functional_Programming_100.png

Functional_Programming_101.png

Functional_Programming_102.png

Functional_Programming_103.png

You can match for specific heads of expressions with _h

Functional_Programming_104.png

Functional_Programming_105.png

Functional_Programming_106.png

Functional_Programming_107.png

Conditions can be added to a pattern with /;

Functional_Programming_108.png

Functional_Programming_109.png

Functional_Programming_110.png

Functional_Programming_111.png

Boolean functions can also be added with the ? operator

Functional_Programming_112.png

Functional_Programming_113.png

Functional_Programming_114.png

Functional_Programming_115.png

Patterns can be combined using | for or

Functional_Programming_116.png

Functional_Programming_117.png

Type checking

Checking for specific heads allows us to perform type checking

Functional_Programming_118.gif

Functional_Programming_119.png

Functional_Programming_120.png

Functional_Programming_121.png

Functional_Programming_122.png

Functional_Programming_123.png

Functional_Programming_124.png

Functional_Programming_125.png

Functional_Programming_126.png

Functional_Programming_127.png

Let’s get rid of our old (overly-general) rule

Functional_Programming_128.png

We want to add a condition to the pattern: only match non-negative integers

Functional_Programming_129.gif

Functional_Programming_130.png

Functional_Programming_131.png

Another example

Functional_Programming_132.gif

Functional_Programming_133.png

Functional_Programming_134.png

Functional_Programming_135.png

Functional_Programming_136.png

Example: defining our own derivative function

We want to differentiate arbitrary expressions

This can be achieved using the basic rules of differentiation:

Linearity

Product rule

Chain rule

We first need the concept of an expression being independent of another expression.
This is achieved using FreeQ

Functional_Programming_137.png

Functional_Programming_138.png

Functional_Programming_139.png

Functional_Programming_140.png

Some common base cases:

Functional_Programming_141.gif

Addition:

Functional_Programming_142.png

Scalar multiplication:

Functional_Programming_143.png

Product rule

Functional_Programming_144.png

Chain rule

Functional_Programming_145.png

(Have to be careful in the above not to match f[x] (so make sure g doesn’t match x), otherwise have infinite recursion)

Functional_Programming_146.png

Functional_Programming_147.png

Functional_Programming_148.png

Functional_Programming_149.png

Functional_Programming_150.png

Functional_Programming_151.png

Functional_Programming_152.png

Functional_Programming_153.png

If we encounter functions whose derivatives we don’t know, it will leave them unevaluated:

Functional_Programming_154.png

Functional_Programming_155.png

Functional_Programming_156.png

Functional_Programming_157.png

We can easily add rules for trigonometric functions:

Functional_Programming_158.gif

Functional_Programming_159.png

Functional_Programming_160.png

Functional_Programming_161.png

Functional_Programming_162.png

Our definitions will automatically work with function composition:

Functional_Programming_163.png

Functional_Programming_164.png

Functional_Programming_165.png

Functional_Programming_166.png

Functional_Programming_167.png

Functional_Programming_168.png

Functional_Programming_169.png

Speed: memoization

Recall our Fibonacci sequence

Functional_Programming_170.gif

How fast (slow?) is it?

Functional_Programming_171.png

Functional_Programming_172.png

Functional_Programming_173.png

Functional_Programming_174.png

Functional_Programming_175.png

Functional_Programming_176.png

Functional_Programming_177.png

Functional_Programming_178.png

Functional_Programming_179.png

Functional_Programming_180.gif

In fact, the runtime for the recursive algorithm satisfies

Functional_Programming_181.png

and so the time to compute fib[n] is actually given by fib[n]

We can easily find a closed form representation of the Fibonacci sequence (involving the golden ratio) using e.g. the characteristic polynomial

Functional_Programming_182.png

Functional_Programming_183.png

Functional_Programming_184.png

Functional_Programming_185.png

Functional_Programming_186.gif

Functional_Programming_187.png

Functional_Programming_188.gif

We can try to optimize our recursive implementation using memoization

Functional_Programming_189.png

Functional_Programming_190.png

Look how many times fib[1] and fib[0] are evaluated! We can speed things up by storing these values

Functional_Programming_191.png

Functional_Programming_192.png

Functional_Programming_193.png

Functional_Programming_194.png

Functional_Programming_195.png

Functional_Programming_196.png

Functional_Programming_197.png

Functional_Programming_198.png

Functional_Programming_199.png

Functional_Programming_200.png

Functional_Programming_201.png

Functional_Programming_202.gif

Functional_Programming_203.png

Functional_Programming_204.gif

Functional_Programming_205.gif

Functional_Programming_206.gif

We can see that the timings are linear, which is clear given the recurrence

Functional_Programming_207.png