Slide 1

Slide 1 text

Functional Programming An Introduction with Clojure

Slide 2

Slide 2 text

Functional Programming ● A programming paradigm based on the lambda calculus ● Close to pure mathematics in terms of abstraction ● No concept of application state ● Treats code as data

Slide 3

Slide 3 text

Clojure ● A Lisp on the JVM and CLR ● Interoperates with JARs and .NET libraries ○ "There is an elephant in the room called all the code we have already written." - Rich Hickey ● C# + Lisp + Java + "closure" = Clojure

Slide 4

Slide 4 text

Values ● 3 ● "hello, world" ● #{ "Tolkien" "Martin" "Butcher" } ● { :lat 34.65 :lon 86.77 :city "Huntsville"}

Slide 5

Slide 5 text

Immutability ● Once a value is set, it cannot be changed ● Can be simulated in C# with readonly ● Example: Aster.Numerics.Vector3D ● Always threadsafe ● Everything in Clojure is immutable

Slide 6

Slide 6 text

Phoenix.Settings and the Mutation Problem ● Phoenix.Settings allows the storage of mutable data objects ● Cannot enforce communication of settings changes to observers ● Forces serialization of entire settings collection to ensure capture of all changes ● Threadsafe?

Slide 7

Slide 7 text

java.util.prefs and the Mutation Problem ● Only allows the use of primitive types ● Suffers from less expressiveness than Phoenix.Settings ● Can properly notify observers of changes

Slide 8

Slide 8 text

Clojure and the Mutation Problem ● Not limited to primitive types ● Does not suffer from lack of expressiveness ● In fact, could build an entire prefs DSL ● Can property notify observers ● Threadsafe!

Slide 9

Slide 9 text

Basic Syntax ● Clojure is a Lisp (and so uses parens a lot) ● Everything is a list ● First element in list is in the operator position and indicates the function to call on the elements that follow ○ Example: (+ 2 3 4)

Slide 10

Slide 10 text

Basic Syntax (cont.) ● Lists of data use the list or quote method, or the ' sugar: ○ (list 1 2 3) => (1 2 3) ○ (quote (1 2 3)) => (1 2 3) ○ '(1 2 3) => (1 2 3) ○ (1 2 3) => error; 1 is not a function

Slide 11

Slide 11 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? 3 + 1 / 2 * 4 - 5 * 3

Slide 12

Slide 12 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? 3 + (1 / 2 * 4) - (5 * 3)

Slide 13

Slide 13 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? 3 + ((1 / 2) * 4) - (5 * 3)

Slide 14

Slide 14 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (3 + ((1 / 2) * 4)) - (5 * 3)

Slide 15

Slide 15 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? ((3 + ((1 / 2) * 4)) - (5 * 3))

Slide 16

Slide 16 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (- (3 + ((1 / 2) * 4)) (5 * 3))

Slide 17

Slide 17 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (- (+ 3 ((1 / 2) * 4)) (5 * 3))

Slide 18

Slide 18 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (- (+ 3 (* (1 / 2) 4)) (* 5 3))

Slide 19

Slide 19 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (- (+ 3 (* (/ 1 2) 4)) (* 5 3))

Slide 20

Slide 20 text

Oh Those Parens! ● The parens really are not that bad... ● Quick - recall your order of operations! ● What is the result of the following (C# rules)? (- (+ 3 (* (/ 1 2) 4)) (* 5 3)) => -10

Slide 21

Slide 21 text

REPL - Read, Evaluate, Print, Loop ● Read code from input into data structures ● Evaluate the data structures ● Print the result to the screen ● Loop back to Read step

Slide 22

Slide 22 text

Functions ● A mapping from an input set to an output set that does not change the input ● Note that these are the same rules as LINQ ● Defined using the defn macro or the fn function (defn square [x] (* x x)) (square 2) => 4

Slide 23

Slide 23 text

Local Variable Binding: let ● Allows you to name a value within a context ● It is like an immutable local variable (let [x (* 2 3)] (prn x)) => 6 nil

Slide 24

Slide 24 text

Higher-order Functions ● Does one of two things: ○ Takes at least one function as a parameter ○ Returns a function public static IEnumerable Where( this IEnumerable source, Func predicate ) Clojure equivalent: (filter pred coll) (filter even? (range 10)) => (2 4 6 8)

Slide 25

Slide 25 text

Anonymous Functions ● In C#, use lambda expressions: ○ x => x > 3 ○ (x,y) => x * y ● In Clojure, uses # expressions: ○ #(> % 3) ○ #(* %1 %2) ● Note that % matches the first parameter, and %1 and %2 are positional parameters

Slide 26

Slide 26 text

Anonymous Functions (defn >3 [coll] (filter #(> % 3) coll)) (>3 '(1 2 3 4 5)) =>(4 5)

Slide 27

Slide 27 text

Homoiconicity ● The representation of a data structure is a data structure in Clojure (and other Lisps) ● Makes it easy to write code that modifies other code ● Makes the translation into an AST easier to visualize

Slide 28

Slide 28 text

AST From C# Statement int x = 1 + 2 * 3 - 4;

Slide 29

Slide 29 text

AST From C# Statement Statement: Assignment int x 1 + 2 * 3 - 4

Slide 30

Slide 30 text

AST From C# Statement Statement: Assignment variable name: x type: int 1 + 2 * 3 - 4

Slide 31

Slide 31 text

AST From C# Statement Statement: Assignment variable name: x type: int ((1 + (2 * 3)) - 4)

Slide 32

Slide 32 text

AST From C# Statement Statement: Assignment variable name: x type: int 4 Expression lhs operator: - rhs ((1 + (2 * 3))

Slide 33

Slide 33 text

AST From C# Statement Statement: Assignment variable name: x type: int number: 4 Expression lhs operator: - rhs rhs operator: + Expression lhs number: 1 rhs operator: * Expression lhs number: 2 number: 3

Slide 34

Slide 34 text

AST from a Clojure Expression (- (+ 1 (* 2 3)) 4)

Slide 35

Slide 35 text

AST from a Clojure Expression - (+ 1 (* 2 3)) 4

Slide 36

Slide 36 text

AST from a Clojure Expression - + 4 1 (* 2 3)

Slide 37

Slide 37 text

AST from a Clojure Expression - + 4 1 * 2 3

Slide 38

Slide 38 text

AST from a Clojure Expression - + 4 1 * 2 3 The syntax is a serialized AST!

Slide 39

Slide 39 text

Macros ● Macros allow you to change the structure of a statement before it gets to the compiler ● It happens during the evaluate step of REPL ● Adds expressiveness, and can be used to build DSLs ● In traditional Lisps, naming conflicts can occur across libraries, but...

Slide 40

Slide 40 text

Macros (cont.) ● Clojure solves this by placing macros in namespaces to avoid naming collisions ● Macros should be used infrequently compared to functions (defmacro when "Evaluates test. If logical true, evaluates body in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body)))

Slide 41

Slide 41 text

But...What about Performance? ● All Clojure code is compiled into bytecode, even during the REPL ○ Maintains awesome performance of the platform ● But copying all that data is expensive right? ○ Since everything is part of a list in Clojure, everything can be represented in trees. ○ You can copy the change from a node into a new tree that shares most of the nodes with the original data tree. ○ This is cheap in both space & time complexity.

Slide 42

Slide 42 text

Pipe Operator ● In F#, the pipe operator ( |> ) is one of the most commonly used operators ● Clojure equivalent is two-fold: -> and ->> ● "Pushes" output to the first and last argument of next statement, respectively ○ ->> is exactly equivalent to |>

Slide 43

Slide 43 text

Bonus: Binary Search (defn binary-search "Searches for the target and returns the index or -1 if not found. Has average complexity of O(log n)." [coll target] ((fn [coll target start end] (let [mid (quot (+ start end) 2) m (nth coll mid)] (cond (> start end) -1 (> target m) (recur coll target (inc mid) end) (< target m) (recur coll target start (dec mid)) (= target m) mid))) coll target 0 (dec (count coll))))

Slide 44

Slide 44 text

Bonus: 4th-order Runge-Kutta (defn rk4 "Implements a fourth-order Runge-Kutta method" [f x y h] (let [k1 (* h (f x y)) k2 (* h (f (+ x (* 1/2 h)) (map #(+ % (* 1/2 k1)) y))) k3 (* h (f (+ x (* 1/2 h)) (map #(+ % (* 1/2 k2)) y))) k4 (* h (f (+ x h) (map #(+ % k3) y))) k (* 1/6 (+ k1 (* 2 k2) (* 2 k3) k4))] [(+ x h) (map #(+ % k) y)]))

Slide 45

Slide 45 text

Bonus: 4th-order Runge-Kutta (defn rk4-seq "Implements a fourth-order Runge-Kutta as an infinite list" [f x y h] ((fn rk4-rec [rx ry] (let [result (rk4 f rx ry h)] (cons [rx ry] (lazy-seq (rk4-rec (first result) (last result)))))) x y)) (take 5 (rk4-seq (fn [x y] (* 2 x)) 0 '(0) 1)) => ([0 (0)] [1 (1)] [2 (4)] [3 (9)] [4 (16)])

Slide 46

Slide 46 text

Bonus: Conway's Game of Life (defn neighbours [[x y]] (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])] [(+ dx x) (+ dy y)])) (defn step [cells] (set (for [[loc n] (frequencies (mapcat neighbours cells)) :when (or (= n 3) (and (= n 2) (cells loc)))] loc))) Source: http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/

Slide 47

Slide 47 text

The Expression Problem The Expression Problem is a new name for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts). - Philip Wadler Source: http://homepages.inf.ed.ac. uk/wadler/papers/expression/expression.txt

Slide 48

Slide 48 text

There Is Much More! ● Records (defrecord) ● Protocols (defprotocol) ● Tail-recursion (recur) ● Lazy sequences (lazy-seq) ● Vectors, arrays, maps ● Concurrency (actors, STM) ● Metadata

Slide 49

Slide 49 text

Links clojure.org clojuredocs.org clojurebook.com github.com/clojure/clojure irc.freenode.net/#clojure

Slide 50

Slide 50 text

More Links Leiningen - a build tool github.com/technomancy/leiningen Incanter - an R-like platform for statistical computing and graphics http://incanter.org Immutant - JBoss AS7-based application server http://immutant.org