The JVM seems to have a fresh breeze blowing throw it with alternative languages like Groovy and Ruby. But for me, the standouts are Scala and Clojure. Many of us grew up with OO and Java was our language of expression. But Scala and Clojure are different. They have a functional side and expressing OO thoughts functionally is painful. We we will explore what it takes to shift your thinking gradually (not overnight) to take advantage of Scala and Clojure's functional side.
2. Not Quite Object Oriented
a frustrating and incomplete journey from OO to FP
Aslam Khan :: @aslamkhn :: +Aslam Khan :: factor10.com :: aslamkhan.net factor10
3. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
4. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
In the beginning,
I used C
5. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
In the beginning, Procedural
I used C C++
6. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
In the beginning, Procedural Procedural
I used C C++ Java
7. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Patterns
In the beginning, Procedural Procedural
and
I used C C++ Java
Polymorphism
8. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns
In the beginning, Procedural Procedural
and Ruby
I used C C++ Java
Polymorphism C#
9. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
10. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
11. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy
JavaScript
12. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented”
JavaScript JavaScript
13. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial
JavaScript JavaScript on Parsers
14. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
15. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
16. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
Object Oriented
Scala
17. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
Object Oriented
Read Haskell
Scala
18. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
Object Oriented More
Read Haskell
Scala Functional Scala
19. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
Object Oriented More
Read Haskell Clojure
Scala Functional Scala
20. My journey in trying to write code
it felt like a language journey, but it’s actually far from that
Java
Patterns Finally
In the beginning, Procedural Procedural
and Ruby Object
I used C C++ Java
Polymorphism Oriented!
C#
then I had to write a parser in JavaScript
Ultra messy “Object Oriented” Haskell Tutorial More functional
JavaScript JavaScript on Parsers JavaScript
inspired to be more functional
Object Oriented More Long mental
Read Haskell Clojure
Scala Functional Scala journey ...
21. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
22. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Try the equivalent in Scala
with some trivial example
23. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Try the equivalent in Scala
with some trivial example
Try it on your project
the essential parts of the problem and solution
24. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Stuck ? Try the equivalent in Scala
(impurity) or (ignorance) ?
with some trivial example
Try it on your project
the essential parts of the problem and solution
25. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Stuck ? Try the equivalent in Scala
(impurity) or (ignorance) ?
with some trivial example
Try it on your project
the essential parts of the problem and solution
26. The language of functional
And there are quite a few new concepts to understand
27. The language of functional
And there are quite a few new concepts to understand
Currying
Algebraic Types
Closures Type Classes
Monads High Order Functions
Pattern Matching Monoids
Functors
Lambdas Polymorphic Functions
List Comprehension
28. The language of functional
And there are quite a few new concepts to understand
Currying
Closures Type Classes
Monads
Monoids
Functors
Lambdas Polymorphic Functions
List Comprehension High Order Functions
Algebraic Types Pattern Matching
29. Let’s write some Java
Find all even integers in a range
List<Integer> xs = range(1,20);
List<Integer> evenRange = evens(xs);
30. Let’s write some Java
Find all even integers in a range
List<Integer> range(int start, int end) {
List<Integer> xs = new ArrayList<Integer>();
for (int i = start; i < end + 1; i++) {
xs.add(i);
}
return xs;
}
List<Integer> xs = range(1,20);
List<Integer> evenRange = evens(xs);
31. Let’s write some Java
Find all even integers in a range
List<Integer> range(int start, int end) {
List<Integer> xs = new ArrayList<Integer>();
for (int i = start; i < end + 1; i++) {
xs.add(i);
}
return xs;
}
List<Integer> xs = range(1,20);
List<Integer> evenRange = evens(xs);
List<Integer> evens(List<Integer> xs) {
List<Integer> keep = new ArrayList<Integer>();
for (Integer x : xs) {
if (isEven(x)) keep.add(x);
}
return keep;
}
32. Let’s write some Java
Find all even integers in a range
List<Integer> range(int start, int end) {
List<Integer> xs = new ArrayList<Integer>();
for (int i = start; i < end + 1; i++) {
xs.add(i);
}
return xs;
}
List<Integer> xs = range(1,20);
List<Integer> evenRange = evens(xs);
List<Integer> evens(List<Integer> xs) {
List<Integer> keep = new ArrayList<Integer>();
for (Integer x : xs) {
if (isEven(x)) keep.add(x);
}
return keep;
}
boolean isEven(Integer x) { return x % 2 == 0; }
33. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
34. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens
35. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens applied to xs
36. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens applied to xs is a list
37. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens applied to xs is a list for each x in xs
38. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens applied to xs is a list for each x in xs where x is even
39. The Haskell way?
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
function evens applied to xs is a list for each x in xs where x is even
for example:
evens [1..20]
40. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
41. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens
42. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens takes from a list xs
43. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens takes from a list xs each x
44. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens takes from a list xs each x in xs
45. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens takes from a list xs each x in xs where x is even
46. And in Scala
list comprehensions are sometimes called for-comprehensions in Scala-land
val evens = (xs: List[Int]) =>
for (x <- xs; even(x) ) yield x
evens takes from a list xs each x in xs where x is even
val even = (x:Int) => x % 2 == 0
47. And in Clojure
Let’s use the built in “filter” function
(defn evens [xs] (filter even? xs))
48. And in Clojure
Let’s use the built in “filter” function
(defn evens [xs] (filter even? xs))
evens
49. And in Clojure
Let’s use the built in “filter” function
(defn evens [xs] (filter even? xs))
evens applied to a list xs
50. And in Clojure
Let’s use the built in “filter” function
(defn evens [xs] (filter even? xs))
evens applied to a list xs applies the filter
51. And in Clojure
Let’s use the built in “filter” function
(defn evens [xs] (filter even? xs))
evens applied to a list xs applies the filter even? on xs
52. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
53. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
54. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
abstract the parts that change
find f xs = [ x | x <- xs, f x ]
55. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
abstract the parts that change
find f xs = [ x | x <- xs, f x ]
using filter f
56. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
abstract the parts that change
find f xs = [ x | x <- xs, f x ]
using filter f on a list xs
57. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
abstract the parts that change
find f xs = [ x | x <- xs, f x ]
using filter f on a list xs for each x in xs
58. What if we have lots of “filters”
Remember: We are using Haskell to understand functional concepts
evens xs = [ x | x <- xs, even x ]
odds xs = [ x | x <- xs, odd x ]
abstract the parts that change
find f xs = [ x | x <- xs, f x ]
using filter f on a list xs for each x in xs where x satisfies the filter f
59. High Order Functions
helps you get DRY and leads to clean compositions
val find = (predicate :Int => Boolean, xs :List[Int]) =>
for (x <- xs; if predicate(x)) yield x
val even = (x :Int) => x % 2 == 0
val odd = (x :Int) => x % 2 == 1
60. High Order Functions
helps you get DRY and leads to clean compositions
val find = (predicate :Int => Boolean, xs :List[Int]) =>
for (x <- xs; if predicate(x)) yield x
use any function which we
locally call predicate
val even = (x :Int) => x % 2 == 0
val odd = (x :Int) => x % 2 == 1
61. High Order Functions
helps you get DRY and leads to clean compositions
val find = (predicate :Int => Boolean, xs :List[Int]) =>
for (x <- xs; if predicate(x)) yield x
use any function which we as long as the provided function takes an
locally call predicate integer and returns a boolean
val even = (x :Int) => x % 2 == 0
val odd = (x :Int) => x % 2 == 1
62. High Order Functions
helps you get DRY and leads to clean compositions
val find = (predicate :Int => Boolean, xs :List[Int]) =>
for (x <- xs; if predicate(x)) yield x
use any function which we as long as the provided function takes an
locally call predicate integer and returns a boolean
val even = (x :Int) => x % 2 == 0
val odd = (x :Int) => x % 2 == 1
63. High Order Functions
helps you get DRY and leads to clean compositions
val find = (predicate :Int => Boolean, xs :List[Int]) =>
for (x <- xs; if predicate(x)) yield x
use any function which we as long as the provided function takes an
locally call predicate integer and returns a boolean
val even = (x :Int) => x % 2 == 0
val odd = (x :Int) => x % 2 == 1
for example
find(even, List.range(0,21))
find(odd, List.range(0,21))
64. And in Clojure
notice how we compose more powerful functions from smaller functions
(defn find [predicate, xs] (filter predicate xs))
65. And in Clojure
notice how we compose more powerful functions from smaller functions
(defn find [predicate, xs] (filter predicate xs))
function
66. And in Clojure
notice how we compose more powerful functions from smaller functions
(defn find [predicate, xs] (filter predicate xs))
function
for example
(find odd? [1,2,3,4])
(find even? [1,2,3,4])
68. Let’s apply this learning
how can we model a few rules?
Non Substitutable
have to downcast to get
the specific type
69. Let’s apply this learning
how can we model a few rules?
Non Substitutable
have to downcast to get
the specific type
70. Let’s apply this learning
how can we model a few rules?
Non Substitutable Semantically Wrong
have to downcast to get how can a FixedTime
the specific type project be over budget?
71. It’s the rules that vary
In Java, using the strategy patterns
72. It’s the rules that vary
In Java, using the strategy patterns
class Project {
public boolean check(CheckProjectRule rule) {
return rule.check(this);
}
}
73. It’s the rules that vary
In Java, using the strategy patterns
class Project {
public boolean check(CheckProjectRule rule) {
return rule.check(this);
}
}
interface ProjectRule {
public boolean check(Project p);
}
74. It’s the rules that vary
In Java, using the strategy patterns
class Project {
public boolean check(CheckProjectRule rule) {
return rule.check(this);
}
}
interface ProjectRule {
public boolean check(Project p);
}
class OverdueProjectRule implements ProjectRule {
...
public boolean check(Project p) {
return p.getEndDate().isBefore(today());
}
}
76. In Scala
Using high order functions
class Project {
val check = (rule :Prj => Boolean) => rule(this)
}
77. In Scala
Using high order functions
class Project {
val check = (rule :Prj => Boolean) => rule(this)
}
val overBudgetRule = (p :Project) =>
p.costToDate() > p.budget()
78. In Scala
Using high order functions
class Project {
val check = (rule :Prj => Boolean) => rule(this)
}
val overBudgetRule = (p :Project) =>
p.costToDate() > p.budget()
val overdueProjectRule = (p :Project) =>
p.getEndDate().isBefore(today())
The Strategy Pattern
is not needed because of high order functions
79. A Model for Shapes
Shape
abstract area()
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
Square
Square(x, y, l)
It’s easy to imagine what the Java code will look like
80. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
Square
Square(x, y, l)
81. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
Square
Square(x, y, l)
82. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
Square
Square(x, y, l)
83. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
Square
Square(x, y, l)
84. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
area :: Shape -> Float
Square
Square(x, y, l)
85. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
area :: Shape -> Float
area (Circle _ _ r) = pi * r^2
Square
area (Rectangle _ _ w h) = w * h
Square(x, y, l)
area (Square _ _ l) = l * l
86. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
area :: Shape -> Float
area (Circle _ _ r) = pi * r^2
Square
area (Rectangle _ _ w h) = w * h
Square(x, y, l)
area (Square _ _ l) = l * l
87. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
area :: Shape -> Float
area (Circle _ _ r) = pi * r^2
Square
area (Rectangle _ _ w h) = w * h
Square(x, y, l)
area (Square _ _ l) = l * l
88. Haskell
not inheritance, but “alternatives” of cases of the type
data Shape = Circle Float Float Float | Shape
Rectangle Float Float Float Float | abstract area()
Square Float Float Float
Circle Rectangle
Circle(x, y, r) Rectangle(x, y, w, h)
area :: Shape -> Float
area (Circle _ _ r) = pi * r^2
Square
area (Rectangle _ _ w h) = w * h
Square(x, y, l)
area (Square _ _ l) = l * l
Algebraic Types
used to construct values for specific cases
91. Shapes in Scala
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
92. Shapes in Scala
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
93. Shapes in Scala
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
94. Shapes in Scala
Algebraic Types
to describe how to construct alternatives
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
95. Shapes in Scala
Algebraic Types
to describe how to construct alternatives
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
Pattern Matching
to specify use cases based on values
96. Shapes in Scala
Algebraic Types
to describe how to construct alternatives
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
Pattern Matching
to specify use cases based on values
val area : Shape => Int = _ match {
}
97. Shapes in Scala
Algebraic Types
to describe how to construct alternatives
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
Pattern Matching
to specify use cases based on values
val area : Shape => Int = _ match {
case Circle( _, _, radius ) => Pi * ( pow( radius, 2.0 ) )
case Rectangle( _, _, width, height ) => width * height
case Square( _, _, length ) => length * length
}
98. Shapes in Scala
Algebraic Types
to describe how to construct alternatives
sealed abstract class Shape
case class Circle( x: Int, y :Int, r :Int) extends Shape
case class Rectangle(x: Int, y :Int, w :Int, h :Int) extends Shape
case class Square(x :Int, y:Int, l :Int) extends Shape
Pattern Matching
to specify use cases based on values
val area : Shape => Int = _ match {
case Circle( _, _, radius ) => Pi * ( pow( radius, 2.0 ) )
case Rectangle( _, _, width, height ) => width * height
case Square( _, _, length ) => length * length
case Rectangle( _, _, 1, height ) => height
case Rectangle( _, _, width, 1 ) => width
}
99. What has been our journey so far?
Maybe we should apply it to something a bit more substantial
List Comprehension
100. What has been our journey so far?
Maybe we should apply it to something a bit more substantial
List Comprehension
High Order Functions
101. What has been our journey so far?
Maybe we should apply it to something a bit more substantial
List Comprehension
High Order Functions
Algebraic Types
102. What has been our journey so far?
Maybe we should apply it to something a bit more substantial
List Comprehension
High Order Functions
Algebraic Types
Pattern Matching
103. A better model for a Project
Using the composite pattern
Activity
Phase Milestone Task Project
104. A better model for a Project
Using the composite pattern
Activity
Phase Milestone Task Project
105. A better model for a Project
Using the composite pattern
Activity
Phase Milestone Task Project
106. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
Phase Milestone Task Project
107. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
case class Task(description: String, person :String)
extends Activity
Phase Milestone Task Project
108. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
Phase Milestone Task Project
109. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
lazy val activities = List (
Phase(1), Phase Milestone Task Project
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
110. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
lazy val activities = List (
Phase(1), Phase Milestone Task Project
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
case class Phase(phaseNumber :Int) extends Activity
111. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
lazy val activities = List (
Phase(1), Phase Milestone Task Project
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
case class Phase(phaseNumber :Int) extends Activity
112. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
trait ManyActivities { def activities :Seq[Activity] }
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
lazy val activities = List (
Phase(1), Phase Milestone Task Project
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
case class Phase(phaseNumber :Int) extends Activity
113. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
trait ManyActivities { def activities :Seq[Activity] }
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
with ManyActivities {
lazy val activities = List ( Phase Milestone Task Project
Phase(1),
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
case class Phase(phaseNumber :Int) extends Activity
114. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
trait ManyActivities { def activities :Seq[Activity] }
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
with ManyActivities {
lazy val activities = List ( Phase Milestone Task Project
Phase(1),
Task("Develop", "Peter"),
Milestone("Release to UAT"),
)
}
case class Phase(phaseNumber :Int) extends Activity
with ManyActivities {
val activities = List(
Task("Analysis", "John"),
Milestone("Ready for Development")
)
}
115. A better model for a Project
Using the composite pattern
sealed abstract class Activity
Activity
trait ManyActivities { def activities :Seq[Activity] }
case class Task(description: String, person :String)
extends Activity
case class Milestone(name :String)
extends Activity
case class Project(name :String) extends Activity
with ManyActivities {
lazy val activities = List ( Phase Milestone Task Project
Phase(1),
Task("Develop", "Peter"),
Milestone("Release to UAT"),
) unapply() is an Extractor for
}
algebraic types
object ManyActivities {
case class Phase(phaseNumber :Int) extends Activity
def unapply(a :Activity) = {
with ManyActivities { a match {
val activities = List( case (a :ManyActivities) => Some(a.activities)
Task("Analysis", "John"), case _ => None
Milestone("Ready for Development") }
) }
} }
116. Actions for this project
Using the visitor pattern
Activity
process (Action)
Phase Milestone Task Project
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
117. Actions for this project
Using the visitor pattern
Activity
process (Action)
Phase Milestone Task Project
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
118. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
119. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
120. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
121. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
Action
for_Phase()
for_Milestone()
for_Task()
for_Project()
Plan Start Status Celebrate
122. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
123. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
124. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
125. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
126. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { process (Action)
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => ()
}
action(a)
} Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
127. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { val prj = Project("HelloWorld") (Action)
process
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => () process(plan)(prj)
}
action(a)
} process(start)(prj) Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
case Milestone(name) => { ... }
case Project(name) => { ... }
} Plan Start Status Celebrate
}
128. With functions
we don’t need the object oriented visitor patterns
def process(action :Activity => Unit)(a :Activity) { Activity
a match { val prj = Project("HelloWorld") (Action)
process
case ManyActivities(activities)
=> activities.foreach(process(action))
case _ => () process(plan)(prj)
}
action(a)
} process(start)(prj) Phase Milestone Task Project
}
def plan(a :Activity) { Action
a match { for_Phase()
for_Milestone()
case Task(description, person) => { ... }
for_Task()
case Phase(number) => { ... } for_Project()
Next Steps
case Milestone(name) => { ... }
Look at Haskell type classes and Scala implicit
case Project(name) => { ... } def for polymorphic functions
} Plan Start Status Celebrate
}
129. Can you take the same journey with Clojure?
Use each step to build confidence, and go pure if you are stuck
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Stuck ? Try equivalent in Clojure
(impurity of Clojure) or (my ignorance) ?
with some trivial example
Try it on your project
the essential parts of the problem and solution
130. Some changes in thinking
as a result of going on this functional journey
Simple Structures Simple Transformations
and
lists and dictionaries list comprehensions, map, reduce
131. Some changes in thinking
as a result of going on this functional journey
Simple Structures Simple Transformations
and
lists and dictionaries list comprehensions, map, reduce
Find a starting set of elements
[ a, b, c, d, e, f ]
132. Some changes in thinking
as a result of going on this functional journey
Simple Structures Simple Transformations
and
lists and dictionaries list comprehensions, map, reduce
Find a starting set of elements
[ a, b, c, d, e, f ]
Transform to what you need
[ (a, b), (c,d) (e, f) ]
133. Some changes in thinking
as a result of going on this functional journey
Simple Structures Simple Transformations
and
lists and dictionaries list comprehensions, map, reduce
Find a starting set of elements
[ a, b, c, d, e, f ]
Transform to what you need
[ (a, b), (c,d) (e, f) ]
Filter to get what you want
[(c,d)]
134. Other things I work hard at
Stop thinking about Remind myself of
and
interactions between objects values of data and transformations
135. Other things I work hard at
Stop thinking about Remind myself of
and
interactions between objects values of data and transformations
Keep it immutable with val
var feels dirty in Scala
136. Other things I work hard at
Stop thinking about Remind myself of
and
interactions between objects values of data and transformations
Keep it immutable with val
var feels dirty in Scala
No unexpected side effects
137. Other things I work hard at
Stop thinking about Remind myself of
and
interactions between objects values of data and transformations
Keep it immutable with val
var feels dirty in Scala
No unexpected side effects
Always return something
makes me consider every branch
138. Benefits that I’ve observed
and some that I have an anticipation that will happen
139. Benefits that I’ve observed
and some that I have an anticipation that will happen
DRY, really DRY
more than I expected
140. Benefits that I’ve observed
and some that I have an anticipation that will happen
DRY, really DRY
more than I expected
Very declarative
makes it very readable too
141. Benefits that I’ve observed
and some that I have an anticipation that will happen
DRY, really DRY
more than I expected
Very declarative
makes it very readable too
Some OO patterns disappear
into trivial implementations
142. Benefits that I’ve observed
and some that I have an anticipation that will happen
DRY, really DRY
more than I expected
Very declarative
makes it very readable too
Some OO patterns disappear
into trivial implementations
Very testable
small, immutable, side-effect free
143. Benefits that I’ve observed
and some that I have an anticipation that will happen
DRY, really DRY
more than I expected
Very declarative
makes it very readable too
Some OO patterns disappear
into trivial implementations
Very testable
small, immutable, side-effect free
Modular
with excellent composition
144. How I now think about code
Primitive expressions
food, I, put, my, mouth, in
A means of combination
I put food in my mouth
A means of abstraction
I eat
This is the basics of understanding and organisation of thought
145. Programs are the same
they express our understanding and show the organisation of our thoughts
146. Programs are the same
they express our understanding and show the organisation of our thoughts
Think
large
static
structures
147. Programs are the same
they express our understanding and show the organisation of our thoughts
Think
large Think
static small
structures
composable
structures
148. Programs are the same
they express our understanding and show the organisation of our thoughts
Th ink
la rge
st atic
ctu res or Think
stru
small
composable
structures
149. The language of functional
And there are quite a few new concepts to understand
Currying
Algebraic Types
Closures Type Classes
Monads High Order Functions
Pattern Matching Monoids
Functors
Lambdas Polymorphic Functions
List Comprehension
150. My functional learning loop
Don’t forget the Haskell talk by Simon Peyton Jones on the Cool Languages Track
Read about
functional concepts
in Haskell
do this slowly … don’t rush!
Stuck ? Try the equivalent in Scala
(impurity) or (ignorance) ?
with some trivial example
Try it on your project
the essential parts of the problem and solution
151. What How do you want to build?
factor10.com :: @aslamkhn :: aslamkhan.net