Functions

The power of Mathematica lies in the enormous number of built-in functions and
the numerous features that can be combined to define complex new functions that
significantly extend the computational capabilities of Mathematica. This allows the
user to quickly expand the abilities of Mathematica in powerful ways.

A function is defined by specifying the name and its argument list, followed by actions
to be performed by the function. The syntax will be clear from a few examples.

In[28]:=

  square[x_]:= x^2;
  

In[29]:=

  square[ 5]

Out[29]=

  25

In[30]:=

  square[ Sqrt[2]]

Out[30]=

  2

In the left side of the definition, we specify the arguments of the function by
placing an underbar after the variable. The := specifies that it is the definition of
a function. After this, we give the rule for the evaluation of a function.

Exercise: Define a function to cube of a number.

It is essential to use the underbar to represent a variable. If you use an underbar,
then any number can be used as an argument. Otherwise, only the argument will
match the expression. For example,

In[31]:=

  
   squareroot[x]:= x^(1/2)

In[32]:=

  squareroot[4]

Out[32]=

  squareroot[4]

In[33]:=

  squareroot[x]

Out[33]=

  Sqrt[x]

In this case, only when the argument of squareroot is x does the function
give the correct value. No other expression matches it because of the lack of
the underbar.

The simplest way to extend the function capabilities is to able to define functions
with different expressions for different ranges of the input variables. Recall that we
did not get the real cube root of -1 in a previous computation. Since the value of
the cube root of a negative number is the negative of the cube root of its absolute
value, we can define a function to give the real valued cube root as follows.

In[34]:=

  realcuberoot[x_]:= (x)^(1/3) /; x>=0;
  realcuberoot[x_]:= - (-x)^(1/3) /; x<0;

This defines a real valued cube root for real numbers. Notice, the definition for
negative numbers. The /; after the expression specifies the conditions under which t
the function is to be evaluated. Let us try this on a few values.

In[35]:=

  realcuberoot[-1]

Out[35]=

  -1

In[36]:=

  realcuberoot[ -8]

Out[36]=

  -2

In[37]:=

  realcuberoot[ 27]

Out[37]=

  3

We can define functions by specifying rules for evaluating the functions. To define
the Fibonacci numbers, we can convert the standard recurrence relation that defines
them into a Mathematica function.

In[38]:=

  fib[1]=1;
  fib[2]=1;
  fib[ n_]:= fib[ n-1] + fib[n-2]
  

In[39]:=

  fib[10]

Out[39]=

  55

In[40]:=

  fib[30]

If you evaluated fib[30] then you would have noticed that the computation took a few
minutes (depending on the speed of your machine). This happens because to evaluate
fib[30], Mathematica first computes fib[29] and fib[28]. To evaluate fib[29] it
has to compute fib[28] and all the smaller Fibonacci numbers, but these intermediate
computations are then thrown away. To compute fib[28], then Mathematica again
computes all the previous values. This is very inefficient in terms of computational time,
so there is a way to tell Mathematica to remember all the intermediate values in
a computation. This is done in the following way. We first make Mathematica
forget the old definition by using the Clear command.

In[41]:=

  Clear[fib]
  fib[1]=1;
  fib[2]=1;
  fib[n_]:= fib[n]= fib[n-1] + fib[n-2]

Here the definition fib[n_]:= fib[n] tells Mathematica to remember all the
intermediate values. Now the computation should work much faster. There are also
ways to compute large Fibonacci numbers directly, without computing all the
previous ones.

Exercise: Define functions to compute n! and |x|.

More detailed description of functions using the Module command are
described in the section on procedural programming.

Up to Tutorial