SlideShare une entreprise Scribd logo
1  sur  118
The Secret Life of a Mathematica Expression

David Leibs
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/mathematica-programminglanguage

InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Presented at QCon San Francisco
www.qconsf.com
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Building Material

“Lisp isn’t a language, it’s a building material”
Alan Kay

There are historically two camps in computing.  One camp creates languages that focus on
making the machine more efficient.  The other camp focuses on making the user more
efficient.  I come from the Lisp, Smalltalk, Mathematica world. In the world of languages that
focus on the user it is sometimes difficult to separate the language from it's environment.
Mathematica is a power tool

•
•
•
•
•
•

Focus on making the user productive
Symbolic
Functional
Rule Based
Amazing Library
Lispy

One can program and explore while backed by the what seems to be all of mathematics. If you
need to do statistics you don't need to go outside and look for a library.
Its just a functional programming language built on top of a rule-based rewrite engine. That is
easy to say but it has profound implications. Operations are on general symbolic trees of
terms. The Mathematica expression is a very simple general framework for the representation
of both data and programs.
You start with a large general rule base and then add your own rules. The systems starts with
the wisdom of the Krell and you build out from there.
The builtins are highly optimized for efficient operations on lists and arrays that are similar to
APL.  There is lots of support for functional programming idioms. There are pure anonymous
functions and efficient higher order functions like Map, Fold, Nest.  All these functions apply to
general mathematica expressions and are not limited to just Lists.
The rule based style lets you easily create languages.  There is even support for overloading
the already built in functions so that your new objects can be used immediately. Meta
programming is natural.  If you need Objects and Classes you can build them yourself or pick
up a standard package. 
Exploration

In[1] :=

Plot[x^2, {x, -5, 5}]

Out[1]:=

25

20

15

10

5

-4

-2

2

4

The Notebook gives you a context for exploration. You make expressions in input cells and
evaluate them. The result appears below in an output cell. It is natural to graph data and
visualize.
Visualization

In[1] :=

Graph[Table[i -> Mod[i^2, 74], {i, 100}]]

Out[1]:=

There is a great library for visualizing almost anything.
Symbolic

In[1] :=

PDF[NormalDistribution[mean, sd]]

Out[1]:=

The symbolic nature let’s you see solutions in a general way. Let’s say you forgot how to
compute the Probability Density Function for a Normal Distribution. Just give the functions
symbolic arguments instead of numeric ones.
Mathematica Expressions

In[1] :=

expression

Out[1]:=

result

Today we will limit ourselves to the Mathematica language.  We will start with the Mathematica
expression.  Like lisp, the mathematica language is homoiconic. That just means that the
language is a mathematica data structure.  Unlike lisp there is just enough convenience syntax
to let you use the same infix functions with operator precedence that you learned in Algebra 1.
A user of mathematics just writes expressions and the evaluator evaluates them.  We are
going to look at a sequence of expressions and talk about what the evaluator does.  
I am going to pretend we are in a notebook evaluating expressions.  Mathematica Notebooks
have an awesome slide show mode but we will just limit ourselves to something static.
Pass 1: Simple Evaluation

In[1] :=

1

Out[1]:=

1

1 is a perfectly good mathematica expression and 1 evaluates to itself.
In[1] :=

2

Out[1]:=

2

Numbers evaluate to themselves.
In[1] :=

“Hello World!”

Out[1]:=

Hello World!

Strings evaluate to themselves and that gets “Hello World” out of the way.
Like a Calculator

In[1] :=

3+7

Out[1]:=

7

You can use Mathematica like a calculator and do arithmetic.
Like Algebra 1

In[1] :=

3+4*5

Out[1]:=

23

This is normal for expressions and the operator precedence is what you learned in Algebra 1.
Someone a long time ago created rules that are designed to make polynomials happy. Go
figure.
Function

In[1] :=

Sqrt[49]

Out[1]:=

7

A function call looks a little different because we use [ and ] instead of ( and ). In Mathematica
parens are for grouping. The Mathematica convention for built in functionality is to always use
an upper case first Character.
Lists

In[1] :=

{3,4,{5,6}}

Out[1]:=

{3,4,{5,6}}

We have Lists and of course they can be nested.
APL Like

In[1] :=

{10,20,30} + 5

Out[1]:=

{15,25,35}

Arithmetic works on Lists as well as one would expect of any reasonable language.
Array Programming

In[1] :=

{10,20,30} + {5,10,20}

Out[1]:=

{15,30,50}

Array Programming style algorithms is natural and one can use many of the array
programming idioms.
Higher Order Functions

In[1] :=

Map[Sqrt, {9,16,25,36}]

Out[1]:=

{3,4,5,6}

There are lots of functions to learn about, a lifetime of functions.  There are plenty of built in
higher order functions for functional programming. The documentation for the functionality in
Mathematica is the best of anything that exists. The documentation is live Notebooks and you
can experiment with the samples.
Pure Functions

In[1] :=

Map[#^2&, {3,4,5,6}]

Out[1]:=

{9,16,25,36}

The #^2& is a shortcut way to make what is called a pure function. The # is an argument. You
can use #1, #2, etc. The & is a postfix way of saying Function.
In[1] :=

Map[ Function[{x},x^2],  {3,4,5,6}]

Out[1]:=

{9,16,25,36}

Here is another way to say the same function but this time it is all spelled out and readable.
In[1] :=

Nest[ # * 1.06&, 100, 10] 

Out[1]:=

179.085

Nest is one of my favorite higher order functions. Nest takes an initial value and an iteration
count and keeps passing the result back into the given function.  Will we ever see 6% interest
again.
In[1] :=

Out[1]:=

NestList[ # * 1.06&, 100, 10] 
{100, 106., 112.36, 119.102, 126.248, 133.823, 141.852,
150.363, 159.385, 168.948, 179.085}

NestList is wonderful, you can see all the values along the way.
We also have Fold, FoldList, FixedPoint, FixedPointList, Select.
In[1] :=

factorial[0] := 1;
factorial[x_] := x*factorial[x - 1];

In[2] :=

factorial[5]

Out[1]:=

120

Let's get factorial out of the way. :-)  We have to do factorial.
This factorial is written is a rule oriented style. We make our cases as separate rules. This
holds the If statements at bay.
Pattern Variable
In[1] :=

factorial[0] := 1;
factorial[x_] := x*factorial[x - 1];

In[2] :=

factorial[5]

Out[1]:=

120

The x_ is how you specify an argument to a function. It is a pattern variable. We will come
back to patterns in the next pass. For now you can think of it like you would an argument to a
function.
In[1] :=

Map[factorial,{3,4,5}]

Out[1]:=

{6, 24, 120}

You can pass our factorial function to Map.
Imperative Constructs

In[1] :=

Out[1]:=

L = {};
For[i = 0, i < 10, i++, 
    L = Append[L, i]];
L
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

There are the usual control constructs like If, While, For, Do, etc. This is just like a gazillion
other languages. This let’s you write in an imperative style if you must. I sometimes have to do
this when I will be translating code to Java.
Why isn’t Mathematica yelling at me?

In[1] :=

x

Out[1]:=

x

Ok, what about this expression? I typed a variable that has no value and I am not getting
yelled at for having done something stupid.
Is this Heresy?

In[1] :=

3+x

Out[1]:=

3+x

Now this is heresy!  I added 3 to an uninitialized variable and didn’t get an error message.
In[1] :=

f[5]

Out[1]:=

f[5]

We are all used to getting yelled at when we use un-initialized variables.  What's going on
here? What if I try to use a function that doesn't exist?
In[1] :=

f[2+3]

Out[1]:=

f[5]

The Mathematica evaluator just evaluates as far as it can and then stops.
Partial

In[1] :=

Map[f, {3,4,5}]

Out[1]:=

{f[3], f[4], f[5]}

What if I pass a function that doesn't exist to a higher order function. That must be disastrous.
No it’s very useful.
Apply is Expression Surgery

In[1] :=

Apply[factorial, %, 1]

Out[1]:=

{6,24,120}

Yes, something is going on here and it isn't a disaster, it's wonderful! I can use Apply and
change the F to our factorial at the first level of the expression. The % signifies the last result.
Yes, it's time to start over. Let's now begin pass 2. In pass 1 I was just setting up some things
for your recognition memory so I won't have to say too much later. Ok, on to pass 2 where it is
time to learn what a Mathematica expression is and we will better introduce “The Evaluator”.
Let’s Start Over

In[1] :=

pass 2

Out[1]:=

pass 2

Mathematica thinks this is Times[2, pass]
Raw Expressions

In[1] :=

1

Out[1]:=

1

Also called Raw Expressions
Strings

In[1] :=

“Hello World”

Out[1]:=

Hello World

Strings evaluate to themselves and print with the quotes gone.
Atoms

In[1] :=

AtomQ[1]

Out[1]:=

True

AtomQ tests to see if an expression is atomic. You also see True which is a symbol.
Symbols

In[1] :=

x

Out[1]:=

x

Characters not in quotes are Symbols and they evaluate to themselves if they do not own a
value.
Rules Not Slots

In[1] :=

x=y

Out[1]:=

y

This expression that looks like an assignment is not assigning to a slot in memory. We create
values for Symbols be making a rule. The Symbol x now owns a value.
Evaluation

In[1] :=

x

Out[1]:=

y

The evaluator takes x, finds a rule, and replaces it with the Symbol y.
In[1] :=

y=1

Out[1]:=

1

We can give y a rule as well.
Repeated Evaluation

In[1] :=

x

Out[1]:=

1

Now the evaluator finds x has a rule that reduces x to y. The evaluator is happy to keep going
so long as it can keep reducing an expression. The Symbol y reduces to 1 and we are done.
Yes, recursion is possible.
In[1] :=

4+x

Out[1]:=

5

This looks normal but remember we went through several reductions.
Quoting

In[1] :=

Hold[1+2]

Out[1]:=

Hold[1+2]

Now Hold is very interesting! Hold is a quoting mechanism. This issue exposes a Use vs.
Mention mechanism. Languages that deal with use vs. mention are very special.  This is Lispy.
Mathematica has many shades of mention. Hold is letting us tell the evaluator to not evaluate
the expression inside the Hold.
Canonicalization

In[1] :=

FullForm[Hold[1+2]]

Out[1]:=

Hold[Plus[1, 2]]

What we see here is the real representation of 1+2.  Mathematica canonicalizes what we type
into a Mathematica expression that is in prefix form.  FullForm is a way to inhibit the uncanonicalizer and lets us see inside to the true Inner Mathematica. We have uniform
Mathematica expressions all the way down.
Expressions

Atom
or
head[exp0, exp1, ... ,expn]

This is the simple definition of a Mathematica expression.

In general a Mathematica expression is an Atom or is a Head (which is usually a symbol)
followed by a square bracket, then a sequence of Mathematica expressions separated by
commas, and ended with a square bracket.
Heads

In[1] :=

Head[a + b]

Out[1]:=

Plus

The function Head let's us get the Head of an expression. Mathematica canonicalizes to a
uniform prefix style internal form.
Heads

In[1] :=

Head[Plus]

Out[1]:=

Symbol

Where is the Head? On Atoms such as numbers, strings, and symbols Mathematica seems to
manufacture a Head.  I think of the head as being like a type.
Evaluation

In[1] :=

Head[3+4]

Out[1]:=

Integer

Mathematica evaluated the expression and passed the result to Head. Remember that we are
working with a building material.
Holding Evaluation

In[1] :=

Head[Hold[3+4]]

Out[1]:=

Hold

Um, this is not quite what we want. Maybe we can reach inside the Hold.
Holding Evaluation

In[1] :=

Head[First[Hold[3+4]]]

Out[1]:=

Integer

Let’s try First which will grab the first element of a general Mathematica expression. Shoot,
the evaluator got it's hands on the expression once First pulled the expression out of Hold. The
Mathematica evaluator wants to evaluate everything in sight until all the pieces won't evaluate
any further.
Holding Evaluation

In[1] :=

Head[Unevaluated[3+4]]

Out[1]:=

Plus

Unevaluated is what we want. Unevaluated works like Hold but it isn't.  Unevaluated is a one
shot thing. You use it to pass expressions without letting the evaluator evaluate them.
Unevaluated is magic and know to the evaluator. Unevaluated is another shade of mention.
You could write your own version of Hold and we will by using Mathematica but Unevaluated is
built into the evaluator.
Juxtaposition is Multiplication

In[1] :=

Map[Head, Unevaluated[3 + 4]]

Out[1]:=

2 Integer

Ok, what the heck happened.
 Map does not have to be given a List.  It works with any Head. It will map the given function
over the elements and give them back in the given Head.
The Evaluator

Map[Head, Unevaluated[3 + 4]]
the evaluator sees:
Map[Head,Plus[3,4]]
and computes:
Plus[Integer,Integer]
but it keeps evaluating and gives
Times[2, Integer]

The evaluator keeps going and going. Integer + Integer is 2 Integer.
The Evaluator

e0 [e1, e2, e3,  … , en]
eval[e0] [eval[e1], eval[e2], eval[e3], …, eval[en]
...
match to rules and possibly rewrite

Ok the evaluator.  I am going to call it eval. Here is what the evaluator wants to do when given
a Mathematica expression.
If eval[e0] produces something that has a rule that matches the list of evaluated arguments
then it replaces it all with that result and does it all again, and again until nothing changes.
Now, at last, the interesting part.  We are ready to look at more shades of mention. We have
seen Unevaluated and Hold.  The evaluator will leave an expression inside of UnEvaluated
alone and pass the expression inside on. If it can't find a rule it puts it back. This can be a little
disconcerting.
Evaluation

In[1] :=

Plus[3+4,5+6]

Out[1]:=

18

The evaluator recursively evaluates Plus[3,4] and Plus[5,6] and matches that form with Plus.
Plus is a built in rule.
The symbol f has no rule

In[1] :=

f[3+4, 5+6]

Out[1]:=

f[7,11]

Like before the evaluator recursively evaluates Plus[3,4] and Plus[5,6] but finds no a rule for f
so it’s work is done.
Apply lets us change a Head

In[1] :=

Apply[Plus, f[3+4, 5+6]]

Out[1]:=

18

Apply lets us change the Head of an expression. We change the head of f[7,11] to Plus and
the evaluator keeps on going. You could name Apply SetHead.
Rules: Set

In[1] :=

x = Random[]

Out[1]:=

0.114681

We set a Symbol’s replacement rule with =. The right hand side of Set is evaluated right now.
x has a value

In[1] :=

{x, x, x}

Out[1]:=

{0.114681, 0.114681, 0.114681}

Each time we rewrite the symbol x the replacement is the same.
Rules: SetDelayed

In[1] :=

y := Random[]

We can set a Symbols replacement rule with := which is SetDelayed. The right hand side of
SetDelayed is not evaluated right now.
Rules: SetDelayed

In[1] :=

{y, y, y}

Out[1]:=

{0.304997, 0.897893, 0.00343832}

The Random[] on the right side will be evaluated every time the evaluator rewrites y.
Rules: OwnValues

In[1] :=

Out[1]:=

{OwnValues[x], OwnValues[y]}
{{HoldPattern[x] :> 0.114681},
{HoldPattern[y] :> Random[]}}

Rather that assigning to memory locations Symbols are bound to values by rules.
Mathematica calls these OwnValues. We will later talk about DownValues, and UpValues.
The :> is RuleDelayed.
HoldPattern is another mention mechanism that is just for patterns.
Patterns

In[1] :=

_

Out[1]:=

_

It’s time to better understand patterns. A pattern is a Mathematica expression that represents
an entire class of expressions.
This is the simplest, Blank[]
Blank

In[1] :=

Hold[_] //FullForm

Out[1]:=

Hold[Blank[]]

Blank is just a regular Mathematica expression.
Blank with Head

In[1] :=

Hold[_f] //FullForm

Out[1]:=

Hold[Blank[f]]

This form of Blank will only match if the expression has a Head that is f.
Matching

•
•
•
•
•
•
•

_

Blank

__ BlankSequence (one or more)
___ BlankNullSequence (0 or more)
|

Alternatives

:

Optional

..

Repeated

?

PatternTest

Patterns are just expressions and Mathematica has a lot of expressive power for building
Pattern expressions.
Matching

In[1] :=

MatchQ[5, _Integer]

Out[1]:=

True

Expressions + Matching is very powerful
Replacement Rules

In[1] :=

5 x + 19.5 x^2 /. v_Real -> v^2

Out[1]:=

5 x + 380.25 x^2

/. is ReplaceAll. I can give ReplaceAll a list of replacement rules. ReplaceAll is a built in that
is like a simplified form the the Mathematica evaluator.
Rules

In[1] :=

Hold[v_Integer -> v^2] // FullForm

Out[1]:=

Hold[Rule[Pattern[v,Blank[Integer]],Power[v,2]]]

Rules are where Mathematica gets its power. Mathematica uses rule based programming
paradigm. You write down a set of rules that specify a transformation to be applied to some
expressions. The system figures out the order in which these rules are to be applied.
Destructuring

In[1] :=

f[m] + g[n] /. x_[y_] -> y[x]

Out[1]:=

m[f] + n[g]

Extracting parts of expressions using pattern variables is called destructuring.
With this capability you can do just about anything. This is why I call Mathematica a building
material.
Factorial Again

In[1] :=

factorial[0] := 1;
factorial[x_] := x*factorial[x - 1];

In[2] :=

factorial[5]

Out[1]:=

120

Here is our factorial again.
DownValues

In[1] :=

Out[1]:=

DownValues[factorial]
{HoldPattern[factorial[0]] :> 1,
HoldPattern[factorial[x_]] :> x factorial[x - 1]}

Let’s look at how factorial is represented as a rule. Remember, HoldPattern is a mention
mechanism and the matching machinery sees right through it. These rules are called
DownValues.
Factorial Matching Style

In[1] :=

fact[5] //. {fact[0] :> 1, fact[x_] :> x * fact[x - 1]}

Out[1]:=

120

This is an interesting inversion of thinking. The syntax //. is for the function
ReplaceRepeated and it keep evaluating until the expression no longer changes. It doesn’t
grow any stack when executed but the expression probably gets longer until the end when
the evaluator gets it’s hand on the expression and reduces all the multiplication.
Look closer with FixedPointList

In[1] :=

FixedPointList[# /. {fact[0] :> 1, fact[x_] :> x * fact[x - 1]} &,
fact[5]]

Out[1]:=

{fact[5], 5 fact[4], 20 fact[3], 60 fact[2], 120 fact[1],
120 fact[0], 120, 120}

Let’s look at it with FixedPointList and ReplaceAll. It looks like it is multiplying the numbers
out before transforming fact[n]. Or is it that the Mathematica evaluator doing it’s things
before we see it?
In[1] :=

f[x_, y_] := body;

In[2] :=

f[a, b]
ReleaseHold[Hold[body] /. {x :> a, y:>b}]

It is best to think of everything mathematica does as term rewriting. This expression could be
step of the evaluator. This is just an approximation because Mathematica has to take scoping
constructs into account but this gives you the idea.
Enough with factorial already!

In[1] :=

Clear[factorial];
factorial[0] := 1;
factorial[x_Integer] := Apply[Times, Range[x]]]
factorial[x_] := Gamma[x-1];

All right, maybe we can really be done with factorial. You want to learn to leverage
Mathematica’s functional building blocks and trans gigantic library. You probably don’t want
to write Gamma yourself.
Symbols have Attributes

•
•
•
•
•
•
•

HoldFirst
HoldRest
HoldAll
Listable
Flat
Orderless
...

There is a way to give the evaluator special instructions by putting some interesting attributes
on a Symbol. We will look at HoldFirst, HoldRest, HoldAll, and Listable. We will try to get to
Flat and Orderless but that will probably have to wait for another day. Flat, and Orderless is
how Mathematica deals with Associativity and Commutativity. Orderless keeps the number of
rules down by Sorting. If it’s Commutative you can sort. There are other attributes that you can
read about in the Mathematica documentation.
Attribute: HoldFirst

In[1] :=

SetAttributes[f,HoldFirst];

In[2] :=

f[3+4, 5+6]

Out[1]:=

f[3+4, 11]

There is a way to give the evaluator special instructions by putting some interesting attributes
on a Symbol. We will look at HoldFirst, HoldRest, and HoldAll
Attribute: HoldRest

In[1] :=

Clear[f];
SetAttributes[f,HoldRest];

In[2] :=

f[3+4, 5+6]

Out[1]:=

f[7, 5+6]

Now we will evaluate the first and hold the rest.
Attribute: HoldAll

In[1] :=

Clear[f];
SetAttributes[f,HoldAll];

In[2] :=

f[3+4, 5+6]

Out[1]:=

f[3+4, 5+6]

We can arrange for the symbol f when used as a head to withhold evaluation for either the first
expression, all but the first, or just hold all of exprssions.
Let's go on a rampage.
Control
In[1] :=

In[2] :=

Out[1]:=

In[2] :=
Out[1]:=

SetAttributes[if, HoldRest];
if[True, thenPart_, elsePart_] := thenPart;
if[False, thenPart_, elsePart_] := elsePart;
x = 10;
if[x < 100, 3+4, 5+6]
7
if[x > 100, 3+4, 5+6]
11

Time to make our own control construct.
When the evaluator sees an expression who’s Head is the symbol if it will evaluate the first
argument and hold evaluation on the rest of the arguments.
We will make a pair of rules for if. One for the True part and one for the False part.
Having the thenPart or the elsePart for the result of the rule just lets the evaluator evaluate
that which was held.
This kind of rule is a DownValue. What looks like a function is usually a DownValue.
The fractorial function from before was a DownValue
Is this a Bug?

In[1] :=

if[100, 3+4, 5+6]

Out[1]:=

if[100, 3+4, 5+6]

Take that!  Is our if construct flawed? The last case is not an error in our if design, it is a
perfectly good expression.  You may learn to like this. The possibly un-expected result is in
your face, preserved so you can see the truth of what is. We could make a new rule for if that
would yell at us but that isn’t really the Mathematica way.
Will It Map?

In[1] :=

Map[if[# < 10, # * #, # + #] &, {5, 6, 25, 50, "die"}]

Out[1]:=

{25, 36, 50, 100, if["die" < 10, "die" "die", "die" + "die"]}

Now we can just use our if in functions and higher order functions.
FEXPRS

Check out the material by John Shutt on Vau-Calculus at:
http://fexpr.blogspot.com.

Back in the old days in Lisp we had FEXPRS but macros won out because they are very
compiler friendly. There is a bit of a revival of FExprs going on.  Check out the material by
John Shutt on vau-calculus at http://fexpr.blogspot.com.
There is nothing special about Hold

In[1] :=

SetAttributes[hold,HoldAll];
releasehold[hold[x___]] := x

In[2] :=

releasehold[hold[3 + 4, 5 + 6]]

Out[1]:=

Sequence[7, 11]

Let’s make our own version of Hold. There is a lot to see here. The pattern variables do not
have to be at the top level. We get a destructuring bind. Sequence is cool. It gets spliced into
expressions and can be controlled with the attribute SequenceHold.
Sequence Splices

In[1] :=

{releasehold[hold[3 + 4, 5 + 6]]}

Out[1]:=

{7, 11}

Let’s just put that expression inside a List and watch Sequence splice. Sequence is a great
building block. One of the attributes is SequenceHold which inhibits the splicing.
Attribute: Listable

In[1] :=

Clear[f];
SetAttributes[f,Listable];

In[2] :=

f[{a,b,c},{d,e,f}]

Out[1]:=

{f[a, d], f[b, e], f[c, f]}

Listable causes the Lists to be threaded over the Symbol. This is APLish but works in a
symbolic environment.
Scoping Constructs

•
•
•
•

Function
With
Block
Module

Ok, rule rewriting is great but if you want to program you need some scoping constructs.
Function: A Very Interesting Head

In[1] :=

Function[3+4]

Out[1]:=

3+4&

First let's look at the most interesting scoping mechanism of all space-time, Function.  
Function is a Mathematic expression. Function the expression is the perfect Head. Remember,
a Head does not have to be limited to a Symbol. Function is the basic deferred evaluation
mechanism for code. It makes code a be literal.
In[1] :=

Function[3 + 4] // FullForm

Out[1]:=

Function[Plus[3,4]]

Here Function acts just like Hold.
In[1] :=

Function[3+4][]

Out[1]:=

7

And here we evaluate it by letting it be the Head of an Expression. This is a SubValue, you can
make your own SubValues. Sadly we will not go there today.
In[1] :=

Function[{x,y}, x + y] [3,4]

Out[1]:=

7

This is how you supply arguments.
Function: A Very Interesting Result

In[1] :=

Function[{x}, Function[{y}, x*y]] [3]

Out[1]:=

Function[{y$}, 3 y$]

Here is a Function that returns a Function. Mathematica makes new variable names because
the x bound in the outer function and is free in the inner function. Ok, let's do that factorial
thing again but with function.
Y: A Very Interesting Function
Avert your eyes!

In[1] :=

y := Function[f, 
Function[x,
f[Function[y, x[x][y]]]][Function[x, f[Function[y, x[x][y]]]]]]

This is one of the right of passage functions for functional programming.  My vote for second
best all time function after eval.  The Y Combinator also known as the fixed point combinator.
Y lets you call a function recursively without needing to have a name for that function.
Don’t try to understand it right now.
Oh No, Factorial Again!
Please don’t look at that result!

In[1] :=

Out[1]:=

factorial = y[Function[f, Function[n, If[ n == 0, 1, n * f[n - 1]]]]]
Function[n$,  If[n$ == 0, 1, n$ Function[y$, Function[x$,
        Function[f, Function[n, If[n == 0, 1, n f[n - 1]]]]
[ Function[y$, x$[x$][y$]]]][ Function[x$,
        Function[f, Function[n, If[n == 0, 1, n f[n - 1]]]]
[Function[y$, x$[x$][y$]]]]][y$]][n$ - 1]]]

So if we pass a function that does what factorial does to Y we get a recursive factorial
function.
It Computes

In[1] :=

factorial[5]

Out[1]:=

120

It worked.
No Names Needed

In[1] :=

y[Function[f, Function[n, If[ n == 0, 1, n * f[n - 1]]]]] [5]

Out[1]:=

120

When it is doing it job y make a function just in time. This is a fixed point for functions.
Read about Y

Read about this wonderful function called Y
at Dick Gabriel's website:
 http://www.dreamsongs.com/Files/WhyOfY.pdf

If you hate this kind of thing no worries. If you think you might be interested I will refer you
to a great article on Y.
With

With[{x = x0, y = y0, z = z0}, expr]

A closely related construct to Function in Mathematica is With.  With comes off as more
syntactic but let's you replace names in an expression with values. The names are local
constants.
The x, y and z are replaced inside the expression before the expression is executed. You can
use it like Lisps Let. It is an essential for meta-programming. You can inject code into held
expressions that are templates then you use Apply on the way out to change the Head to
Function.
Meta Programming
In[1] :=

strides[dims_] := Map[Apply[Times, #] &,
NestList[Rest, Rest[dims ~Join~ {1}], Length[dims] - 1]];
indexer[shape_] :=
With[{syms = Map[Unique[a] &, shape], shp = strides[shape]},
With[{pat = 1 + (Plus @@ Apply[Times, Partition[Riffle[syms, shp], 2], 1])},
Function @@ Hold[syms, pat]]];

In[2] :=

indexer[{3, 3, 9}]

Out[1]:=

Function[{a$69734, a$69735, a$69736}, 1 + 27 a$69734 + 9 a$69735 + a$69736]

Sorry for the different font size. With is an essential for meta-programming. You can inject
code into held expressions that are templates then you use Apply on the way out to change
the Head to Function.
Block

In[1] :=

{x, y, z} = {3, 4, 5};

In[2] :=

Block[{x = 10, y = 20, z = 30}, {x, y, z}]

Out[1]:=

{10, 20, 30}

In[3] :=

{x, y, z}

Out[2]:=

{3,4,5}

Block has some of the taste of old Lisp's dynamic binding.   This is useful when you
sometimes want to set a global to a different value during an evaluation and then have it return
to what it was. Think of this as having the ability to have local values.
Module

Module[{x,y,...}, expr]
Module[{x = x0, y = y0, …}, expr]

Finally there is Module. Module let's you setup a local environment where the names are local
to the module.
Module creates new symbols with gensym to represent the variable names each time module
is called.
In[1] :=

Out[1]:=

Module[{l = {}, count = 10, i},
    For[i = 0, i < count, i++, 
        l = Append[l, i]];
l]
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

You can use Module to keep your locals in their own scope.
This is terrible Mathematica Code but sometimes you just need to be imperative.
Make Y Combinator Pretty

In[1] :=

y := Function[f,
Module[{g = Function[h, Function[x, f[h[h]][x]]]}, g[g]]];

Let me wash the stink of imperative code off by using Module to make Y combinator pretty.
Make Objects in a Functional Way

In[1] :=

makeAccount[name_, start_] :=
Module[{accname = name, balance = start},
account[
Function[accname],
Function[x,balance = balance + x],
Function[x,balance = balance - x],
Function[balance]]];

Let’s have a little bit of fun and make Objects out of closures. This is a classic style from SICP
Structure and Interpretation of Computer Programs. The head account acts like a struct that
holds our functions.
Cool, but what an ugly expression

In[1] :=

Out[1]:=

acc1 = makeAccount["david", 1000]
account[
accname$89163 &,
Function[x$, balance$89163 = balance$89163 + x$],
 Function[x$, balance$89163 = balance$89163 - x$],
balance$89163 &]

Now that result is an expression only a mother could love. Not the gensymed symbols.
FormatValues

In[1] :=

Format[account[n_Function, _, _, _]]
:= StringJoin["account[", n[], "]"];

In[2] :=

acc1

Out[1]:=

account[david]

Here is another kind of capability for Symbols. Format let’s us talk to the mechanism that
displays expressions that have the Symbol account for a Head. Now the account object does
not look so ugly and we can’t see inside it unless we use FullForm
Standard DownValue
In[1] :=

name[account[n_Function, _, _, _]]
:= n[];
deposit[account[_, d_Function, _, _], amt_] := d[amt];
withdraw[account[_, _, w_Function, _], amt_] := w[amt];
balance[account[_, _, _, b_Function]]
:= b[];

In[2] :=

balance[acc1]

Out[1]:=

1000

You see here that I am going to match different functions in the account object.  The evaluator
will do a destructuring  bind for us. The _ pattern matches anything. Putting the Head Function
on bf_Function is saying that the evaluator should only match if we are given a Function. I
hear you signature purists screaming.  What if I made a bad function and stuffed it inside an
account.  That would be so sad. :-( Note, we could generate these functions with a little bit of
meta-programming.
UpValues

In[1] :=

account /: Plus[a : account[___], b_]
:= b + balance[a];
account /: Plus[a : account[___] , b : account[___]]
:= balance[a] + balance[b];

In[2] :=

acc1 + 100

Out[1]:=

1100

In[3] :=

acc1 + acc1

Out[2]:=

2000

We could open up Plus and add a new definition but that would slow down all arithmetic.
Instead we will create an UpValue. This kind of rule goes with the Symbol account. The
evaluator looks at the Heads of arguments and finds a match and evaluates our rule.
Think of DownValues as looking from the symbol that is the Head downward into the
expression. Think of UpValues as being down in the expression and looking upward towards
the Head.
Fibonachi

In[1] :=

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

In[2] :=

Array[fib, 8]

Out[1]:=

{1, 2, 3, 5, 13, 21, 34}

Here is classic fibonachi.
Memoizing Fibonachi

In[1] :=

In[2] :=

Out[1]:=

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

We can use DownValues as a little database. This is good for memoizing;
Make Transformation Rules

ClearAll[pushR, popR, dupR, swapR, rotR, topR, nextR];
(* stack-to-stack transforms *)
pushR = {{stack___}, datum_} :> {datum, stack};
popR = {{top_, rest___} :> {rest}};
dupR = {{top_, rest___} :> {top, top, rest}};
rotR = {{top_, rest___} :> {rest, top}};
swapR = {{top_, next_, rest___} :> {next, top, rest}};
(* stack-to-value transforms *)
topR = {{top_, rest___} :> top};
nextR = {{top_, next_, rest___} :> next};

The rule based programming with rewrite rules lets us make languages. Brian Beckman
encouraged me to make the effort to invert my thinking about programming. This is one of the
things he taunted me with. These are stack-to-stack transforms for a Fourth like language.
They are all defined as rules. The stack is maintained as a list. I just draw a picture of the
stack with literal expressions involving patterns and let the matcher do the work.
Microcode for a Fourth Machine
ClearAll[exec,execAll];
microcode = Dispatch@{
(*BINARIES*)
{stack_,plus}:>With[{r=(stack/.nextR)+(stack/.topR)},
{stack/.popR/.popR,r}/.pushR],
{stack_,times}:>With[{r=(stack/.nextR)*(stack/.topR)},
{stack/.popR/.popR,r}/.pushR],
{stack_,minus}:>With[{r=(stack/.nextR)-(stack/.topR)},
{stack/.popR/.popR,r}/.pushR],
{stack_,div}:>With[{r=(stack/.nextR)/(stack/.topR)},
{stack/.popR/.popR,r}/.pushR],
{stack_,uminus}:>({stack/.popR,-(stack/.topR)} /. pushR),
(*NULLARIES*)
{stack_,pop}:>(stack/.popR),
{stack_,dup}:>(stack/.dupR),
{stack_,rot}:>(stack/.rotR),
{stack_,swap}:>(stack/.swapR),
(*UNARY-- DEFAULT*)
{stack_,x_}:>({stack,x}/.pushR)};

Here are more rules. Dispatch builds compiles the rules into something that efficiently
executes the transformations.
A little functional code

exec = machineState : {stack_, instr_} :> (machineState /. microcode);
execAll = {stack_, {instr_, instrs___}} :> ({{stack, instr} /. exec, {instrs}});
execute[stack_, instrs_] := First[First[FixedPoint[x ⊂ x /. execAll, {stack, instrs}]]];
execAllTrace[stack_, instrs_] :=
Module[{history = First /@ FixedPointList[x ⊂ x /. execAll, {stack, instrs}] // Most},
Grid[Partition[Join[{start}, Riffle[history, instrs]], 2], Frame -> All]];

We use a functional style to sequence the execution of the rules. FixedPoint is the iteration
pattern that works best here. We also build a visualization interface with FixedPointList so we
can observe the execution in a human understandable way.
Execute and Observe

In[1] :=

execAllTrace[{}, {a, b, 3, 4, plus, rot, div, plus}]

Out[1]:=

I always had a hard time with Fourth because I just couldn’t keep what the evaluator was
doing in my head. Here I can see what is happening. I like to externalized the processs of
execution with some kind of visualization. This is like distributed cognition. Of course I can
just do it symbolically too. I have built array programming languages that animate the
intermediate results of the data flow as the computation moves from expression to
expression.
Compiling

In[1] :=

cP1 = Compile[{{x}},
Module[{sum = 1.0, inc = 1.0},
Do[inc = inc*x/i; sum = sum + inc, {i, 10000}]; sum],
RuntimeAttributes -> {Listable}, Parallelization -> True,
CompilationTarget -> "C"];

In[2] :=

arg = Range[ -50., 50, 0.02];
cP1[arg]; // AbsoluteTiming

Out[1]:=

{0.4531395, Null}

This example comes right out of the Mathematica Documentation Notebook.
Compiling is very cool and let’s you build things that scale very well. When you combine the
ability of meta-programming, partial-evaluation, and all of mathematics with the ability to
compile at a function level of granularity you can do some amazing things.
Watch the video with slide synchronization on
InfoQ.com!
http://www.infoq.com/presentations/mathematica
-programming-language

Contenu connexe

Plus de C4Media

Plus de C4Media (20)

Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 
Navigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery TeamsNavigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery Teams
 
High Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in AdtechHigh Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in Adtech
 
Rust's Journey to Async/await
Rust's Journey to Async/awaitRust's Journey to Async/await
Rust's Journey to Async/await
 
Opportunities and Pitfalls of Event-Driven Utopia
Opportunities and Pitfalls of Event-Driven UtopiaOpportunities and Pitfalls of Event-Driven Utopia
Opportunities and Pitfalls of Event-Driven Utopia
 
Datadog: a Real-Time Metrics Database for One Quadrillion Points/Day
Datadog: a Real-Time Metrics Database for One Quadrillion Points/DayDatadog: a Real-Time Metrics Database for One Quadrillion Points/Day
Datadog: a Real-Time Metrics Database for One Quadrillion Points/Day
 
Are We Really Cloud-Native?
Are We Really Cloud-Native?Are We Really Cloud-Native?
Are We Really Cloud-Native?
 
CockroachDB: Architecture of a Geo-Distributed SQL Database
CockroachDB: Architecture of a Geo-Distributed SQL DatabaseCockroachDB: Architecture of a Geo-Distributed SQL Database
CockroachDB: Architecture of a Geo-Distributed SQL Database
 

Dernier

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 

Dernier (20)

Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 

The Secret Life of a Mathematica Expression

  • 1. The Secret Life of a Mathematica Expression David Leibs
  • 2. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /mathematica-programminglanguage InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month
  • 3. Presented at QCon San Francisco www.qconsf.com Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide
  • 4. Building Material “Lisp isn’t a language, it’s a building material” Alan Kay There are historically two camps in computing.  One camp creates languages that focus on making the machine more efficient.  The other camp focuses on making the user more efficient.  I come from the Lisp, Smalltalk, Mathematica world. In the world of languages that focus on the user it is sometimes difficult to separate the language from it's environment.
  • 5. Mathematica is a power tool • • • • • • Focus on making the user productive Symbolic Functional Rule Based Amazing Library Lispy One can program and explore while backed by the what seems to be all of mathematics. If you need to do statistics you don't need to go outside and look for a library. Its just a functional programming language built on top of a rule-based rewrite engine. That is easy to say but it has profound implications. Operations are on general symbolic trees of terms. The Mathematica expression is a very simple general framework for the representation of both data and programs. You start with a large general rule base and then add your own rules. The systems starts with the wisdom of the Krell and you build out from there. The builtins are highly optimized for efficient operations on lists and arrays that are similar to APL.  There is lots of support for functional programming idioms. There are pure anonymous functions and efficient higher order functions like Map, Fold, Nest.  All these functions apply to general mathematica expressions and are not limited to just Lists. The rule based style lets you easily create languages.  There is even support for overloading the already built in functions so that your new objects can be used immediately. Meta programming is natural.  If you need Objects and Classes you can build them yourself or pick up a standard package. 
  • 6. Exploration In[1] := Plot[x^2, {x, -5, 5}] Out[1]:= 25 20 15 10 5 -4 -2 2 4 The Notebook gives you a context for exploration. You make expressions in input cells and evaluate them. The result appears below in an output cell. It is natural to graph data and visualize.
  • 7. Visualization In[1] := Graph[Table[i -> Mod[i^2, 74], {i, 100}]] Out[1]:= There is a great library for visualizing almost anything.
  • 8. Symbolic In[1] := PDF[NormalDistribution[mean, sd]] Out[1]:= The symbolic nature let’s you see solutions in a general way. Let’s say you forgot how to compute the Probability Density Function for a Normal Distribution. Just give the functions symbolic arguments instead of numeric ones.
  • 9. Mathematica Expressions In[1] := expression Out[1]:= result Today we will limit ourselves to the Mathematica language.  We will start with the Mathematica expression.  Like lisp, the mathematica language is homoiconic. That just means that the language is a mathematica data structure.  Unlike lisp there is just enough convenience syntax to let you use the same infix functions with operator precedence that you learned in Algebra 1. A user of mathematics just writes expressions and the evaluator evaluates them.  We are going to look at a sequence of expressions and talk about what the evaluator does.   I am going to pretend we are in a notebook evaluating expressions.  Mathematica Notebooks have an awesome slide show mode but we will just limit ourselves to something static.
  • 10. Pass 1: Simple Evaluation In[1] := 1 Out[1]:= 1 1 is a perfectly good mathematica expression and 1 evaluates to itself.
  • 12. In[1] := “Hello World!” Out[1]:= Hello World! Strings evaluate to themselves and that gets “Hello World” out of the way.
  • 13. Like a Calculator In[1] := 3+7 Out[1]:= 7 You can use Mathematica like a calculator and do arithmetic.
  • 14. Like Algebra 1 In[1] := 3+4*5 Out[1]:= 23 This is normal for expressions and the operator precedence is what you learned in Algebra 1. Someone a long time ago created rules that are designed to make polynomials happy. Go figure.
  • 15. Function In[1] := Sqrt[49] Out[1]:= 7 A function call looks a little different because we use [ and ] instead of ( and ). In Mathematica parens are for grouping. The Mathematica convention for built in functionality is to always use an upper case first Character.
  • 16. Lists In[1] := {3,4,{5,6}} Out[1]:= {3,4,{5,6}} We have Lists and of course they can be nested.
  • 17. APL Like In[1] := {10,20,30} + 5 Out[1]:= {15,25,35} Arithmetic works on Lists as well as one would expect of any reasonable language.
  • 18. Array Programming In[1] := {10,20,30} + {5,10,20} Out[1]:= {15,30,50} Array Programming style algorithms is natural and one can use many of the array programming idioms.
  • 19. Higher Order Functions In[1] := Map[Sqrt, {9,16,25,36}] Out[1]:= {3,4,5,6} There are lots of functions to learn about, a lifetime of functions.  There are plenty of built in higher order functions for functional programming. The documentation for the functionality in Mathematica is the best of anything that exists. The documentation is live Notebooks and you can experiment with the samples.
  • 20. Pure Functions In[1] := Map[#^2&, {3,4,5,6}] Out[1]:= {9,16,25,36} The #^2& is a shortcut way to make what is called a pure function. The # is an argument. You can use #1, #2, etc. The & is a postfix way of saying Function.
  • 21. In[1] := Map[ Function[{x},x^2],  {3,4,5,6}] Out[1]:= {9,16,25,36} Here is another way to say the same function but this time it is all spelled out and readable.
  • 22. In[1] := Nest[ # * 1.06&, 100, 10]  Out[1]:= 179.085 Nest is one of my favorite higher order functions. Nest takes an initial value and an iteration count and keeps passing the result back into the given function.  Will we ever see 6% interest again.
  • 23. In[1] := Out[1]:= NestList[ # * 1.06&, 100, 10]  {100, 106., 112.36, 119.102, 126.248, 133.823, 141.852, 150.363, 159.385, 168.948, 179.085} NestList is wonderful, you can see all the values along the way. We also have Fold, FoldList, FixedPoint, FixedPointList, Select.
  • 24. In[1] := factorial[0] := 1; factorial[x_] := x*factorial[x - 1]; In[2] := factorial[5] Out[1]:= 120 Let's get factorial out of the way. :-)  We have to do factorial. This factorial is written is a rule oriented style. We make our cases as separate rules. This holds the If statements at bay.
  • 25. Pattern Variable In[1] := factorial[0] := 1; factorial[x_] := x*factorial[x - 1]; In[2] := factorial[5] Out[1]:= 120 The x_ is how you specify an argument to a function. It is a pattern variable. We will come back to patterns in the next pass. For now you can think of it like you would an argument to a function.
  • 26. In[1] := Map[factorial,{3,4,5}] Out[1]:= {6, 24, 120} You can pass our factorial function to Map.
  • 27. Imperative Constructs In[1] := Out[1]:= L = {}; For[i = 0, i < 10, i++,      L = Append[L, i]]; L {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} There are the usual control constructs like If, While, For, Do, etc. This is just like a gazillion other languages. This let’s you write in an imperative style if you must. I sometimes have to do this when I will be translating code to Java.
  • 28. Why isn’t Mathematica yelling at me? In[1] := x Out[1]:= x Ok, what about this expression? I typed a variable that has no value and I am not getting yelled at for having done something stupid.
  • 29. Is this Heresy? In[1] := 3+x Out[1]:= 3+x Now this is heresy!  I added 3 to an uninitialized variable and didn’t get an error message.
  • 30. In[1] := f[5] Out[1]:= f[5] We are all used to getting yelled at when we use un-initialized variables.  What's going on here? What if I try to use a function that doesn't exist?
  • 31. In[1] := f[2+3] Out[1]:= f[5] The Mathematica evaluator just evaluates as far as it can and then stops.
  • 32. Partial In[1] := Map[f, {3,4,5}] Out[1]:= {f[3], f[4], f[5]} What if I pass a function that doesn't exist to a higher order function. That must be disastrous. No it’s very useful.
  • 33. Apply is Expression Surgery In[1] := Apply[factorial, %, 1] Out[1]:= {6,24,120} Yes, something is going on here and it isn't a disaster, it's wonderful! I can use Apply and change the F to our factorial at the first level of the expression. The % signifies the last result. Yes, it's time to start over. Let's now begin pass 2. In pass 1 I was just setting up some things for your recognition memory so I won't have to say too much later. Ok, on to pass 2 where it is time to learn what a Mathematica expression is and we will better introduce “The Evaluator”.
  • 34. Let’s Start Over In[1] := pass 2 Out[1]:= pass 2 Mathematica thinks this is Times[2, pass]
  • 36. Strings In[1] := “Hello World” Out[1]:= Hello World Strings evaluate to themselves and print with the quotes gone.
  • 37. Atoms In[1] := AtomQ[1] Out[1]:= True AtomQ tests to see if an expression is atomic. You also see True which is a symbol.
  • 38. Symbols In[1] := x Out[1]:= x Characters not in quotes are Symbols and they evaluate to themselves if they do not own a value.
  • 39. Rules Not Slots In[1] := x=y Out[1]:= y This expression that looks like an assignment is not assigning to a slot in memory. We create values for Symbols be making a rule. The Symbol x now owns a value.
  • 40. Evaluation In[1] := x Out[1]:= y The evaluator takes x, finds a rule, and replaces it with the Symbol y.
  • 41. In[1] := y=1 Out[1]:= 1 We can give y a rule as well.
  • 42. Repeated Evaluation In[1] := x Out[1]:= 1 Now the evaluator finds x has a rule that reduces x to y. The evaluator is happy to keep going so long as it can keep reducing an expression. The Symbol y reduces to 1 and we are done. Yes, recursion is possible.
  • 43. In[1] := 4+x Out[1]:= 5 This looks normal but remember we went through several reductions.
  • 44. Quoting In[1] := Hold[1+2] Out[1]:= Hold[1+2] Now Hold is very interesting! Hold is a quoting mechanism. This issue exposes a Use vs. Mention mechanism. Languages that deal with use vs. mention are very special.  This is Lispy. Mathematica has many shades of mention. Hold is letting us tell the evaluator to not evaluate the expression inside the Hold.
  • 45. Canonicalization In[1] := FullForm[Hold[1+2]] Out[1]:= Hold[Plus[1, 2]] What we see here is the real representation of 1+2.  Mathematica canonicalizes what we type into a Mathematica expression that is in prefix form.  FullForm is a way to inhibit the uncanonicalizer and lets us see inside to the true Inner Mathematica. We have uniform Mathematica expressions all the way down.
  • 46. Expressions Atom or head[exp0, exp1, ... ,expn] This is the simple definition of a Mathematica expression. In general a Mathematica expression is an Atom or is a Head (which is usually a symbol) followed by a square bracket, then a sequence of Mathematica expressions separated by commas, and ended with a square bracket.
  • 47. Heads In[1] := Head[a + b] Out[1]:= Plus The function Head let's us get the Head of an expression. Mathematica canonicalizes to a uniform prefix style internal form.
  • 48. Heads In[1] := Head[Plus] Out[1]:= Symbol Where is the Head? On Atoms such as numbers, strings, and symbols Mathematica seems to manufacture a Head.  I think of the head as being like a type.
  • 49. Evaluation In[1] := Head[3+4] Out[1]:= Integer Mathematica evaluated the expression and passed the result to Head. Remember that we are working with a building material.
  • 50. Holding Evaluation In[1] := Head[Hold[3+4]] Out[1]:= Hold Um, this is not quite what we want. Maybe we can reach inside the Hold.
  • 51. Holding Evaluation In[1] := Head[First[Hold[3+4]]] Out[1]:= Integer Let’s try First which will grab the first element of a general Mathematica expression. Shoot, the evaluator got it's hands on the expression once First pulled the expression out of Hold. The Mathematica evaluator wants to evaluate everything in sight until all the pieces won't evaluate any further.
  • 52. Holding Evaluation In[1] := Head[Unevaluated[3+4]] Out[1]:= Plus Unevaluated is what we want. Unevaluated works like Hold but it isn't.  Unevaluated is a one shot thing. You use it to pass expressions without letting the evaluator evaluate them. Unevaluated is magic and know to the evaluator. Unevaluated is another shade of mention. You could write your own version of Hold and we will by using Mathematica but Unevaluated is built into the evaluator.
  • 53. Juxtaposition is Multiplication In[1] := Map[Head, Unevaluated[3 + 4]] Out[1]:= 2 Integer Ok, what the heck happened.  Map does not have to be given a List.  It works with any Head. It will map the given function over the elements and give them back in the given Head.
  • 54. The Evaluator Map[Head, Unevaluated[3 + 4]] the evaluator sees: Map[Head,Plus[3,4]] and computes: Plus[Integer,Integer] but it keeps evaluating and gives Times[2, Integer] The evaluator keeps going and going. Integer + Integer is 2 Integer.
  • 55. The Evaluator e0 [e1, e2, e3,  … , en] eval[e0] [eval[e1], eval[e2], eval[e3], …, eval[en] ... match to rules and possibly rewrite Ok the evaluator.  I am going to call it eval. Here is what the evaluator wants to do when given a Mathematica expression. If eval[e0] produces something that has a rule that matches the list of evaluated arguments then it replaces it all with that result and does it all again, and again until nothing changes. Now, at last, the interesting part.  We are ready to look at more shades of mention. We have seen Unevaluated and Hold.  The evaluator will leave an expression inside of UnEvaluated alone and pass the expression inside on. If it can't find a rule it puts it back. This can be a little disconcerting.
  • 56. Evaluation In[1] := Plus[3+4,5+6] Out[1]:= 18 The evaluator recursively evaluates Plus[3,4] and Plus[5,6] and matches that form with Plus. Plus is a built in rule.
  • 57. The symbol f has no rule In[1] := f[3+4, 5+6] Out[1]:= f[7,11] Like before the evaluator recursively evaluates Plus[3,4] and Plus[5,6] but finds no a rule for f so it’s work is done.
  • 58. Apply lets us change a Head In[1] := Apply[Plus, f[3+4, 5+6]] Out[1]:= 18 Apply lets us change the Head of an expression. We change the head of f[7,11] to Plus and the evaluator keeps on going. You could name Apply SetHead.
  • 59. Rules: Set In[1] := x = Random[] Out[1]:= 0.114681 We set a Symbol’s replacement rule with =. The right hand side of Set is evaluated right now.
  • 60. x has a value In[1] := {x, x, x} Out[1]:= {0.114681, 0.114681, 0.114681} Each time we rewrite the symbol x the replacement is the same.
  • 61. Rules: SetDelayed In[1] := y := Random[] We can set a Symbols replacement rule with := which is SetDelayed. The right hand side of SetDelayed is not evaluated right now.
  • 62. Rules: SetDelayed In[1] := {y, y, y} Out[1]:= {0.304997, 0.897893, 0.00343832} The Random[] on the right side will be evaluated every time the evaluator rewrites y.
  • 63. Rules: OwnValues In[1] := Out[1]:= {OwnValues[x], OwnValues[y]} {{HoldPattern[x] :> 0.114681}, {HoldPattern[y] :> Random[]}} Rather that assigning to memory locations Symbols are bound to values by rules. Mathematica calls these OwnValues. We will later talk about DownValues, and UpValues. The :> is RuleDelayed. HoldPattern is another mention mechanism that is just for patterns.
  • 64. Patterns In[1] := _ Out[1]:= _ It’s time to better understand patterns. A pattern is a Mathematica expression that represents an entire class of expressions. This is the simplest, Blank[]
  • 65. Blank In[1] := Hold[_] //FullForm Out[1]:= Hold[Blank[]] Blank is just a regular Mathematica expression.
  • 66. Blank with Head In[1] := Hold[_f] //FullForm Out[1]:= Hold[Blank[f]] This form of Blank will only match if the expression has a Head that is f.
  • 67. Matching • • • • • • • _ Blank __ BlankSequence (one or more) ___ BlankNullSequence (0 or more) | Alternatives : Optional .. Repeated ? PatternTest Patterns are just expressions and Mathematica has a lot of expressive power for building Pattern expressions.
  • 69. Replacement Rules In[1] := 5 x + 19.5 x^2 /. v_Real -> v^2 Out[1]:= 5 x + 380.25 x^2 /. is ReplaceAll. I can give ReplaceAll a list of replacement rules. ReplaceAll is a built in that is like a simplified form the the Mathematica evaluator.
  • 70. Rules In[1] := Hold[v_Integer -> v^2] // FullForm Out[1]:= Hold[Rule[Pattern[v,Blank[Integer]],Power[v,2]]] Rules are where Mathematica gets its power. Mathematica uses rule based programming paradigm. You write down a set of rules that specify a transformation to be applied to some expressions. The system figures out the order in which these rules are to be applied.
  • 71. Destructuring In[1] := f[m] + g[n] /. x_[y_] -> y[x] Out[1]:= m[f] + n[g] Extracting parts of expressions using pattern variables is called destructuring. With this capability you can do just about anything. This is why I call Mathematica a building material.
  • 72. Factorial Again In[1] := factorial[0] := 1; factorial[x_] := x*factorial[x - 1]; In[2] := factorial[5] Out[1]:= 120 Here is our factorial again.
  • 73. DownValues In[1] := Out[1]:= DownValues[factorial] {HoldPattern[factorial[0]] :> 1, HoldPattern[factorial[x_]] :> x factorial[x - 1]} Let’s look at how factorial is represented as a rule. Remember, HoldPattern is a mention mechanism and the matching machinery sees right through it. These rules are called DownValues.
  • 74. Factorial Matching Style In[1] := fact[5] //. {fact[0] :> 1, fact[x_] :> x * fact[x - 1]} Out[1]:= 120 This is an interesting inversion of thinking. The syntax //. is for the function ReplaceRepeated and it keep evaluating until the expression no longer changes. It doesn’t grow any stack when executed but the expression probably gets longer until the end when the evaluator gets it’s hand on the expression and reduces all the multiplication.
  • 75. Look closer with FixedPointList In[1] := FixedPointList[# /. {fact[0] :> 1, fact[x_] :> x * fact[x - 1]} &, fact[5]] Out[1]:= {fact[5], 5 fact[4], 20 fact[3], 60 fact[2], 120 fact[1], 120 fact[0], 120, 120} Let’s look at it with FixedPointList and ReplaceAll. It looks like it is multiplying the numbers out before transforming fact[n]. Or is it that the Mathematica evaluator doing it’s things before we see it?
  • 76. In[1] := f[x_, y_] := body; In[2] := f[a, b] ReleaseHold[Hold[body] /. {x :> a, y:>b}] It is best to think of everything mathematica does as term rewriting. This expression could be step of the evaluator. This is just an approximation because Mathematica has to take scoping constructs into account but this gives you the idea.
  • 77. Enough with factorial already! In[1] := Clear[factorial]; factorial[0] := 1; factorial[x_Integer] := Apply[Times, Range[x]]] factorial[x_] := Gamma[x-1]; All right, maybe we can really be done with factorial. You want to learn to leverage Mathematica’s functional building blocks and trans gigantic library. You probably don’t want to write Gamma yourself.
  • 78. Symbols have Attributes • • • • • • • HoldFirst HoldRest HoldAll Listable Flat Orderless ... There is a way to give the evaluator special instructions by putting some interesting attributes on a Symbol. We will look at HoldFirst, HoldRest, HoldAll, and Listable. We will try to get to Flat and Orderless but that will probably have to wait for another day. Flat, and Orderless is how Mathematica deals with Associativity and Commutativity. Orderless keeps the number of rules down by Sorting. If it’s Commutative you can sort. There are other attributes that you can read about in the Mathematica documentation.
  • 79. Attribute: HoldFirst In[1] := SetAttributes[f,HoldFirst]; In[2] := f[3+4, 5+6] Out[1]:= f[3+4, 11] There is a way to give the evaluator special instructions by putting some interesting attributes on a Symbol. We will look at HoldFirst, HoldRest, and HoldAll
  • 80. Attribute: HoldRest In[1] := Clear[f]; SetAttributes[f,HoldRest]; In[2] := f[3+4, 5+6] Out[1]:= f[7, 5+6] Now we will evaluate the first and hold the rest.
  • 81. Attribute: HoldAll In[1] := Clear[f]; SetAttributes[f,HoldAll]; In[2] := f[3+4, 5+6] Out[1]:= f[3+4, 5+6] We can arrange for the symbol f when used as a head to withhold evaluation for either the first expression, all but the first, or just hold all of exprssions. Let's go on a rampage.
  • 82. Control In[1] := In[2] := Out[1]:= In[2] := Out[1]:= SetAttributes[if, HoldRest]; if[True, thenPart_, elsePart_] := thenPart; if[False, thenPart_, elsePart_] := elsePart; x = 10; if[x < 100, 3+4, 5+6] 7 if[x > 100, 3+4, 5+6] 11 Time to make our own control construct. When the evaluator sees an expression who’s Head is the symbol if it will evaluate the first argument and hold evaluation on the rest of the arguments. We will make a pair of rules for if. One for the True part and one for the False part. Having the thenPart or the elsePart for the result of the rule just lets the evaluator evaluate that which was held. This kind of rule is a DownValue. What looks like a function is usually a DownValue. The fractorial function from before was a DownValue
  • 83. Is this a Bug? In[1] := if[100, 3+4, 5+6] Out[1]:= if[100, 3+4, 5+6] Take that!  Is our if construct flawed? The last case is not an error in our if design, it is a perfectly good expression.  You may learn to like this. The possibly un-expected result is in your face, preserved so you can see the truth of what is. We could make a new rule for if that would yell at us but that isn’t really the Mathematica way.
  • 84. Will It Map? In[1] := Map[if[# < 10, # * #, # + #] &, {5, 6, 25, 50, "die"}] Out[1]:= {25, 36, 50, 100, if["die" < 10, "die" "die", "die" + "die"]} Now we can just use our if in functions and higher order functions.
  • 85. FEXPRS Check out the material by John Shutt on Vau-Calculus at: http://fexpr.blogspot.com. Back in the old days in Lisp we had FEXPRS but macros won out because they are very compiler friendly. There is a bit of a revival of FExprs going on.  Check out the material by John Shutt on vau-calculus at http://fexpr.blogspot.com.
  • 86. There is nothing special about Hold In[1] := SetAttributes[hold,HoldAll]; releasehold[hold[x___]] := x In[2] := releasehold[hold[3 + 4, 5 + 6]] Out[1]:= Sequence[7, 11] Let’s make our own version of Hold. There is a lot to see here. The pattern variables do not have to be at the top level. We get a destructuring bind. Sequence is cool. It gets spliced into expressions and can be controlled with the attribute SequenceHold.
  • 87. Sequence Splices In[1] := {releasehold[hold[3 + 4, 5 + 6]]} Out[1]:= {7, 11} Let’s just put that expression inside a List and watch Sequence splice. Sequence is a great building block. One of the attributes is SequenceHold which inhibits the splicing.
  • 88. Attribute: Listable In[1] := Clear[f]; SetAttributes[f,Listable]; In[2] := f[{a,b,c},{d,e,f}] Out[1]:= {f[a, d], f[b, e], f[c, f]} Listable causes the Lists to be threaded over the Symbol. This is APLish but works in a symbolic environment.
  • 89. Scoping Constructs • • • • Function With Block Module Ok, rule rewriting is great but if you want to program you need some scoping constructs.
  • 90. Function: A Very Interesting Head In[1] := Function[3+4] Out[1]:= 3+4& First let's look at the most interesting scoping mechanism of all space-time, Function.   Function is a Mathematic expression. Function the expression is the perfect Head. Remember, a Head does not have to be limited to a Symbol. Function is the basic deferred evaluation mechanism for code. It makes code a be literal.
  • 91. In[1] := Function[3 + 4] // FullForm Out[1]:= Function[Plus[3,4]] Here Function acts just like Hold.
  • 92. In[1] := Function[3+4][] Out[1]:= 7 And here we evaluate it by letting it be the Head of an Expression. This is a SubValue, you can make your own SubValues. Sadly we will not go there today.
  • 93. In[1] := Function[{x,y}, x + y] [3,4] Out[1]:= 7 This is how you supply arguments.
  • 94. Function: A Very Interesting Result In[1] := Function[{x}, Function[{y}, x*y]] [3] Out[1]:= Function[{y$}, 3 y$] Here is a Function that returns a Function. Mathematica makes new variable names because the x bound in the outer function and is free in the inner function. Ok, let's do that factorial thing again but with function.
  • 95. Y: A Very Interesting Function Avert your eyes! In[1] := y := Function[f,  Function[x, f[Function[y, x[x][y]]]][Function[x, f[Function[y, x[x][y]]]]]] This is one of the right of passage functions for functional programming.  My vote for second best all time function after eval.  The Y Combinator also known as the fixed point combinator. Y lets you call a function recursively without needing to have a name for that function. Don’t try to understand it right now.
  • 96. Oh No, Factorial Again! Please don’t look at that result! In[1] := Out[1]:= factorial = y[Function[f, Function[n, If[ n == 0, 1, n * f[n - 1]]]]] Function[n$,  If[n$ == 0, 1, n$ Function[y$, Function[x$,         Function[f, Function[n, If[n == 0, 1, n f[n - 1]]]] [ Function[y$, x$[x$][y$]]]][ Function[x$,         Function[f, Function[n, If[n == 0, 1, n f[n - 1]]]] [Function[y$, x$[x$][y$]]]]][y$]][n$ - 1]]] So if we pass a function that does what factorial does to Y we get a recursive factorial function.
  • 98. No Names Needed In[1] := y[Function[f, Function[n, If[ n == 0, 1, n * f[n - 1]]]]] [5] Out[1]:= 120 When it is doing it job y make a function just in time. This is a fixed point for functions.
  • 99. Read about Y Read about this wonderful function called Y at Dick Gabriel's website:  http://www.dreamsongs.com/Files/WhyOfY.pdf If you hate this kind of thing no worries. If you think you might be interested I will refer you to a great article on Y.
  • 100. With With[{x = x0, y = y0, z = z0}, expr] A closely related construct to Function in Mathematica is With.  With comes off as more syntactic but let's you replace names in an expression with values. The names are local constants. The x, y and z are replaced inside the expression before the expression is executed. You can use it like Lisps Let. It is an essential for meta-programming. You can inject code into held expressions that are templates then you use Apply on the way out to change the Head to Function.
  • 101. Meta Programming In[1] := strides[dims_] := Map[Apply[Times, #] &, NestList[Rest, Rest[dims ~Join~ {1}], Length[dims] - 1]]; indexer[shape_] := With[{syms = Map[Unique[a] &, shape], shp = strides[shape]}, With[{pat = 1 + (Plus @@ Apply[Times, Partition[Riffle[syms, shp], 2], 1])}, Function @@ Hold[syms, pat]]]; In[2] := indexer[{3, 3, 9}] Out[1]:= Function[{a$69734, a$69735, a$69736}, 1 + 27 a$69734 + 9 a$69735 + a$69736] Sorry for the different font size. With is an essential for meta-programming. You can inject code into held expressions that are templates then you use Apply on the way out to change the Head to Function.
  • 102. Block In[1] := {x, y, z} = {3, 4, 5}; In[2] := Block[{x = 10, y = 20, z = 30}, {x, y, z}] Out[1]:= {10, 20, 30} In[3] := {x, y, z} Out[2]:= {3,4,5} Block has some of the taste of old Lisp's dynamic binding.   This is useful when you sometimes want to set a global to a different value during an evaluation and then have it return to what it was. Think of this as having the ability to have local values.
  • 103. Module Module[{x,y,...}, expr] Module[{x = x0, y = y0, …}, expr] Finally there is Module. Module let's you setup a local environment where the names are local to the module. Module creates new symbols with gensym to represent the variable names each time module is called.
  • 104. In[1] := Out[1]:= Module[{l = {}, count = 10, i},     For[i = 0, i < count, i++,          l = Append[l, i]]; l] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} You can use Module to keep your locals in their own scope. This is terrible Mathematica Code but sometimes you just need to be imperative.
  • 105. Make Y Combinator Pretty In[1] := y := Function[f, Module[{g = Function[h, Function[x, f[h[h]][x]]]}, g[g]]]; Let me wash the stink of imperative code off by using Module to make Y combinator pretty.
  • 106. Make Objects in a Functional Way In[1] := makeAccount[name_, start_] := Module[{accname = name, balance = start}, account[ Function[accname], Function[x,balance = balance + x], Function[x,balance = balance - x], Function[balance]]]; Let’s have a little bit of fun and make Objects out of closures. This is a classic style from SICP Structure and Interpretation of Computer Programs. The head account acts like a struct that holds our functions.
  • 107. Cool, but what an ugly expression In[1] := Out[1]:= acc1 = makeAccount["david", 1000] account[ accname$89163 &, Function[x$, balance$89163 = balance$89163 + x$],  Function[x$, balance$89163 = balance$89163 - x$], balance$89163 &] Now that result is an expression only a mother could love. Not the gensymed symbols.
  • 108. FormatValues In[1] := Format[account[n_Function, _, _, _]] := StringJoin["account[", n[], "]"]; In[2] := acc1 Out[1]:= account[david] Here is another kind of capability for Symbols. Format let’s us talk to the mechanism that displays expressions that have the Symbol account for a Head. Now the account object does not look so ugly and we can’t see inside it unless we use FullForm
  • 109. Standard DownValue In[1] := name[account[n_Function, _, _, _]] := n[]; deposit[account[_, d_Function, _, _], amt_] := d[amt]; withdraw[account[_, _, w_Function, _], amt_] := w[amt]; balance[account[_, _, _, b_Function]] := b[]; In[2] := balance[acc1] Out[1]:= 1000 You see here that I am going to match different functions in the account object.  The evaluator will do a destructuring  bind for us. The _ pattern matches anything. Putting the Head Function on bf_Function is saying that the evaluator should only match if we are given a Function. I hear you signature purists screaming.  What if I made a bad function and stuffed it inside an account.  That would be so sad. :-( Note, we could generate these functions with a little bit of meta-programming.
  • 110. UpValues In[1] := account /: Plus[a : account[___], b_] := b + balance[a]; account /: Plus[a : account[___] , b : account[___]] := balance[a] + balance[b]; In[2] := acc1 + 100 Out[1]:= 1100 In[3] := acc1 + acc1 Out[2]:= 2000 We could open up Plus and add a new definition but that would slow down all arithmetic. Instead we will create an UpValue. This kind of rule goes with the Symbol account. The evaluator looks at the Heads of arguments and finds a match and evaluates our rule. Think of DownValues as looking from the symbol that is the Head downward into the expression. Think of UpValues as being down in the expression and looking upward towards the Head.
  • 111. Fibonachi In[1] := fib[0] = fib[1] = 1; fib[n_] := fib[n-1] + fib[n-2]; In[2] := Array[fib, 8] Out[1]:= {1, 2, 3, 5, 13, 21, 34} Here is classic fibonachi.
  • 112. Memoizing Fibonachi In[1] := In[2] := Out[1]:= Clear[fib]; fib[0] = fib[1] = 1; fib[n_] := fib[n] = fib[n-1] + fib[n-2]; fib[100] 573147844013817084101 We can use DownValues as a little database. This is good for memoizing;
  • 113. Make Transformation Rules ClearAll[pushR, popR, dupR, swapR, rotR, topR, nextR]; (* stack-to-stack transforms *) pushR = {{stack___}, datum_} :> {datum, stack}; popR = {{top_, rest___} :> {rest}}; dupR = {{top_, rest___} :> {top, top, rest}}; rotR = {{top_, rest___} :> {rest, top}}; swapR = {{top_, next_, rest___} :> {next, top, rest}}; (* stack-to-value transforms *) topR = {{top_, rest___} :> top}; nextR = {{top_, next_, rest___} :> next}; The rule based programming with rewrite rules lets us make languages. Brian Beckman encouraged me to make the effort to invert my thinking about programming. This is one of the things he taunted me with. These are stack-to-stack transforms for a Fourth like language. They are all defined as rules. The stack is maintained as a list. I just draw a picture of the stack with literal expressions involving patterns and let the matcher do the work.
  • 114. Microcode for a Fourth Machine ClearAll[exec,execAll]; microcode = Dispatch@{ (*BINARIES*) {stack_,plus}:>With[{r=(stack/.nextR)+(stack/.topR)}, {stack/.popR/.popR,r}/.pushR], {stack_,times}:>With[{r=(stack/.nextR)*(stack/.topR)}, {stack/.popR/.popR,r}/.pushR], {stack_,minus}:>With[{r=(stack/.nextR)-(stack/.topR)}, {stack/.popR/.popR,r}/.pushR], {stack_,div}:>With[{r=(stack/.nextR)/(stack/.topR)}, {stack/.popR/.popR,r}/.pushR], {stack_,uminus}:>({stack/.popR,-(stack/.topR)} /. pushR), (*NULLARIES*) {stack_,pop}:>(stack/.popR), {stack_,dup}:>(stack/.dupR), {stack_,rot}:>(stack/.rotR), {stack_,swap}:>(stack/.swapR), (*UNARY-- DEFAULT*) {stack_,x_}:>({stack,x}/.pushR)}; Here are more rules. Dispatch builds compiles the rules into something that efficiently executes the transformations.
  • 115. A little functional code exec = machineState : {stack_, instr_} :> (machineState /. microcode); execAll = {stack_, {instr_, instrs___}} :> ({{stack, instr} /. exec, {instrs}}); execute[stack_, instrs_] := First[First[FixedPoint[x ⊂ x /. execAll, {stack, instrs}]]]; execAllTrace[stack_, instrs_] := Module[{history = First /@ FixedPointList[x ⊂ x /. execAll, {stack, instrs}] // Most}, Grid[Partition[Join[{start}, Riffle[history, instrs]], 2], Frame -> All]]; We use a functional style to sequence the execution of the rules. FixedPoint is the iteration pattern that works best here. We also build a visualization interface with FixedPointList so we can observe the execution in a human understandable way.
  • 116. Execute and Observe In[1] := execAllTrace[{}, {a, b, 3, 4, plus, rot, div, plus}] Out[1]:= I always had a hard time with Fourth because I just couldn’t keep what the evaluator was doing in my head. Here I can see what is happening. I like to externalized the processs of execution with some kind of visualization. This is like distributed cognition. Of course I can just do it symbolically too. I have built array programming languages that animate the intermediate results of the data flow as the computation moves from expression to expression.
  • 117. Compiling In[1] := cP1 = Compile[{{x}}, Module[{sum = 1.0, inc = 1.0}, Do[inc = inc*x/i; sum = sum + inc, {i, 10000}]; sum], RuntimeAttributes -> {Listable}, Parallelization -> True, CompilationTarget -> "C"]; In[2] := arg = Range[ -50., 50, 0.02]; cP1[arg]; // AbsoluteTiming Out[1]:= {0.4531395, Null} This example comes right out of the Mathematica Documentation Notebook. Compiling is very cool and let’s you build things that scale very well. When you combine the ability of meta-programming, partial-evaluation, and all of mathematics with the ability to compile at a function level of granularity you can do some amazing things.
  • 118. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations/mathematica -programming-language