Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.

Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.

Like this document? Why not share!

1,566 views

Published on

David Leibs unveils some of features of Mathematica Programming Language, a functional and dynamically typed programming language. Filmed at qconsf.com.

David Leibs is a Senior Researcher at Oracle Labs. His research interests include Graphical Programming Languages, Compiler Front-ends, Domain Specific Languages, Meta-Programming, Active Libraries, and Array Programming languages. David is currently in the Virtual Machine Research Group working on a "reactive" and "lively" graphical programming interface used for technical computing.

Published in:
Technology

No Downloads

Total views

1,566

On SlideShare

0

From Embeds

0

Number of Embeds

12

Shares

0

Downloads

0

Comments

0

Likes

3

No embeds

No notes for slide

- 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 efﬁcient. The other camp focuses on making the user more efﬁcient. I come from the Lisp, Smalltalk, Mathematica world. In the world of languages that focus on the user it is sometimes difﬁcult 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 efﬁcient 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 efﬁcient 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 inﬁx 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.
- 11. In[1] := 2 Out[1]:= 2 Numbers evaluate to themselves.
- 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 ﬁgure.
- 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 ﬁrst 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 postﬁx 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 ﬁrst level of the expression. The % signiﬁes 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]
- 35. Raw Expressions In[1] := 1 Out[1]:= 1 Also called Raw Expressions
- 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, ﬁnds 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 ﬁnds 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 preﬁx 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 deﬁnition 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 preﬁx 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 ﬁrst 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 ﬁnd 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 ﬁnds 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.
- 68. Matching In[1] := MatchQ[5, _Integer] Out[1]:= True Expressions + Matching is very powerful
- 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 simpliﬁed 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 ﬁgures 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 ﬁrst 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 ﬁrst expression, all but the ﬁrst, 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 ﬁrst 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 ﬂawed? 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 ﬁxed 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.
- 97. It Computes In[1] := factorial[5] Out[1]:= 120 It worked.
- 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 ﬁxed 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[Rifﬂe[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 deﬁnition 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 ﬁnds 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] := ﬁb[0] = ﬁb[1] = 1; ﬁb[n_] := ﬁb[n-1] + ﬁb[n-2]; In[2] := Array[ﬁb, 8] Out[1]:= {1, 2, 3, 5, 13, 21, 34} Here is classic ﬁbonachi.
- 112. Memoizing Fibonachi In[1] := In[2] := Out[1]:= Clear[ﬁb]; ﬁb[0] = ﬁb[1] = 1; ﬁb[n_] := ﬁb[n] = ﬁb[n-1] + ﬁb[n-2]; ﬁb[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 deﬁned 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}, Rifﬂe[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 ﬂow 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

No public clipboards found for this slide

×
### Save the most important slides with Clipping

Clipping is a handy way to collect and organize the most important slides from a presentation. You can keep your great finds in clipboards organized around topics.

Be the first to comment