MATH299M/CMSC389W - Visualization through Mathematica
Week 2: Basics II: Defining Functions, Implicit Functions, Table, Map

Defining Functions

You can define your own functions, the name must start with a letter and contain letters and numbers, case-sensitive. To do this, type the name of the function, brackets, and inside the brackets the arguments followed each by an underscore, the  := and the contents of the function. Here’s an example:

foo[x_]:=(x^2)+x+1;
{foo[1],foo[2],foo[3]}

SuperPower[x_,y_,z_]:=(x^(y^z));
{SuperPower[2,2,2],SuperPower[2,3,4],SuperPower[4,3,2]}

Mathematica doesn’t have a preconceived assumption about what type of object the variable is, so with the same notation you can create functions that take in lists.

LengthScale[lst_]:=Length[lst]*lst; (* Weird function that multiplies every element of the list (the argument) by the length of the list *)
LengthScale[{1,1,2,3,5,8}]

You can specify the type of argument but it’s not advised, making Mathematica typed makes things clunky and caused more harm than good. Anyone using the code knows what the input should be, and there are better ways to handle improper usage of the functions.

If the argument is a list that we would like to interpret as a tuple with named entries, we can do that:

Complexify[{x_,y_}]:=x+I*y; (* By the way, Esc-ii-Esc gives I which is Mathematica's notation for the imaginary unit (Sqrt[-1]) *)
Complexify[{2,3}]^2

If you don’t care about a certain argument, then you can use just an underscore instead of using up RAM to give it a name:

Project[{x_,y_,_}]:={x,y}; (* Projects a point in 3 space onto the xy plane *)
Project[{2,3,4}]

You can in general force the form of the arguments to be anything:

Unproject[{x_,y_,0}]:={x,y,1}; (* Takes a point in 3-space confined to the xy plane and gives it a z value of 1 *)
Unproject[{1,2,0}]

You can also have a function be an argument:

PlaceOnSurface[{x_,y_},f_]:={x,y,f[x,y]}; (* Takes point in 3-space on xy plane and gives it z value according to the surface defined by the function of two variables passed in as the second argument *)
TentThing[x_,y_]:=x*y; (* Some surface *)
PlaceOnSurface[{2,3},TentThing]
(* This will return the point in three space that our function of two variables maps {x,y} to on the surface *)

You can overload functions by using different argument specifications, great for inputs of variable forms

PowerTower[x_,y_,z_,w_]:=x^(y^(z^w));
PowerTower[{x_,y_,z_,w_}]:=x^(y^(z^w));
PowerTower[3,2,3,2]
PowerTower[{3,2,3,2}]

If your input is ambiguous enough that a given input could satisfy two forms, Mathematica is pretty smart and will take the one that fits best

MultiplySorta[x_,y_,0]:=x*y;
MultiplySorta[x_,y_,z_]:=x*y*z;
MultiplySorta[5,6,0]

MultiplySorta2[x_,y_,z_]:=x*y*z;
MultiplySorta2[x_,y_,0]:=x*y;
MultiplySorta2[5,6,0]

Overloading is also extremely useful for recursion; here is Selection Sort for lists without duplicates:

SelectionSort[{}]:={}; (* Base case *)
SelectionSort[lst_]:=Join[{Min[lst]},SelectionSort[DeleteCases[lst,Min[lst]]]]; (* Recursive step *)
SelectionSort[{3,1,4,5,9,2,6,8,7}]

Map

Map is your best friend! Besides Table, Table and Map are your best friends. Really they do the exact same thing, so you can choose which one you want to be best friends with, but keep the other one close. Anyway, Map takes in two arguments, a function and a list, and then it returns the function applied to every element of that list, very useful for doing a lot of computations quickly. After being exposed to this tool it’s going to feel barbaric to do a lot of things by hand anymore.

Square[x_]:=x^2;
Map[Square,{1,2,3,4,5}]

Map[Sin,π/4*Range[0,16]]

Map has an alternate notation using /@, which I don’t prefer, but it exists:

Square/@{1,2,3,4}

Table

Table is given an argument that is a statement with a variable and then an argument that is a tuple containing a variable of iteration, a start, an end, and then an optional element that is the step size, defaulted to 1, and then outputs a list of the statement evaluated for each term of the variable iterated through, so a For loop:

Table[n,{n,1,10}]

Table[(n^2),{n,1,10}]

Table[(n^2),{n,1,10,2}]

Table[(n^2)+n,{n,1,10,1}](* It's my personal style to put the redundant 1 for the step size in the iterator tuple for table, but you by no means need to do this *)

You can give it a second (or third, etc.) iterator tuple to iterate through another variable once it’s completed the first, so like nested For loops:

Table[x*y,{x,1,4},{y,1,4}]

Table[Table[x*y,{x,1,4}],{y,1,4}] (* This is equivalent to the form above *)

You can also use Table to iterate a variable over a specific set through a slight change in notation where in the iterator tuple the second element is the list to iterate over:

Table[(n^2),{n,{1,1,2,3,5,8}}]

Even if it doesn’t seem like it right now, these functions are going to prove EXTREMELY useful to you - or maybe not, I know that my style of coding relies on them heavily, maybe yours won’t! I’m interested to see. Anyway, to drive the point home of how these are the same thing, I’ll write them in each other; part of MyTable you won’t understand until the next section on implicit functions, but that’s okay, you can come back to it:

MyMap[foo_,lst_]:=Table[foo[var],{var,lst}];
MyMap[Square,{1,2,3}]

MyTable[body_,{var_,lst_}]:=Map[(body/.{var->#})&,lst]; 
MyTable[Square[n],{n,{1,2,3}}]

Implicit (Pure) Functions

Implicit functions and Apply are great to know - it makes it so whatever you need to happen you can do. Sometimes doing things the right way is a headache but it’s important to know what you can do.

Functions are objects that are basically rules that take in input and produce a corresponding output. In Mathematica we can construct these function objects without giving them names for cases where we only need to use the function once, it often makes for more elegant and concise code than introducing helper functions. An implicit function is always terminated with a &, and before that any instance where the input to the function is to go is denoted by a #. Mathematica calls them “pure functions” in the documentation, “implicit functions” is just what I like to call them. Here’s an example of a function being called in Table and it’s implicit version:

Cube[x_]:=x^3;
Map[Cube,{1,2,3,5,8,13}]

Map[(#^3)&,{1,2,3,5,8,13}]

Foo[x_]:=(x^2)+x;
Map[Foo,{1,2,3,5,8,13}]

Map[(((#)^2)+#)&,{1,2,3,5,8,13}]

Here we use a new function called Apply, which takes in a function and a tuple and then applies the elements of that tuple as the arguments of the function.

Pow[x_,y_]:=x^y;
Apply[Pow,{2,3}]

Map[Apply[Pow,#]&,{{1,1},{2,3},{3,5}}]

We can also implicitly define functions of multiple variables by using numbers after the hashes to indicate which argument we’re referring to, #1,#2, etc. The only time I’ve personally ever used this is with the Fold function though, see below.

Fold

Fold is a very useful function that pairs nicely with map and is among the basic tools coders know how to use in (basically) any language they learn. It takes three arguments, a function, a starting variable, and a list. The function takes in two values, the first is always an accumulator, something that changes step to step, and the second argument iterates through the list; the function returns the new value of the accumulator, and the starting variable is what the accumulator starts at.

Add[total_,addend_]:=total+addend;
Fold[Add,0,{1,2,3,4,5,6,7,8,9,10}]

Sentence[sent_,word_]:=sent<>" "<>word;
Fold[Sentence,"",{"Mathematica","is","awesome!"}]

Here are implicit versions of these applications of fold, that is, without explicitly defining the helper function:

Fold[(#1+#2)&,0,{1,2,3,4,5,6,7,8,9,10}]

Fold[(#1<>" "<>#2)&,"",{"Mathematica","is","awesome!"}]

Fold is a recursive function, writing it may be illuminating as to exactly how it works:

MyFold[f_,acc_,{}]:=acc;
MyFold[f_,acc_,lst_]:=MyFold[f,f[acc,lst[[1]]],Delete[lst,1]];

MyFold[(#1+#2)&,0,{1,2,3,4,5,6,7,8,9,10}]
MyFold[(#1<>" "<>#2)&,"",{"Mathematica","is","awesome!"}]

Ajeet Gary - University of Maryland Experimental Geometry Lab
MATH299M/CMSC389W Fall 2018
September 1st, 2018