What is functional programming? This talk sets out to demystify the functional programming paradigm, debunk common myths, and reveal examples of why FP is advantageous compared to imperative programming.
16. “A functional programming language is
a language that emphasises
programming with pure functions and
immutable data
17. Functional Programming
Declarative
Describe what, not how
Expressions over statements
Idempotent
Immutability
Functions are without side-effects
Results deterministic
Referentially Transparent
Any expression can be replaced with
the results of its value
Algebraic
Types, equality, expressions
Category theory
Functionally Composable
Separate behavior from data
Small functions composed together
to make small building blocks
Parallelizable
Idempotent code by nature enables
local and distributed parallelization
18. Myths
✘Requires a math degree to understand
✘Targets only math/science problems
✘Only relevant in academic circles
✘Not for “Line of Business” or “Form Over Data” apps
27. JVM Languages
Scala
✘ Statically strong typed
✘ FP with OOP good parts
✘ Higher-order functions
✘ Insanely advanced type system
✘ Currying, lazy-evaluation, pattern matching, etc.
✘ Large commercial adoption
Twitter, Spotify, LinkedIn, Apache Spark, Kafka, etc.
✘ Backed by Lightbend + Scala Centre
Clojure
✘ Dynamically typed
✘ First-order functions
✘ S-expressions
✘ LISP-dialect
“Modern LISP that is symbiotic with Java”
28. .NET Languages
F#
✘ Statically typed
✘ Multi-paradigm: FP, imperative, OOP
✘ .NET Framework
✘ Visual Studio Tooling
✘ Backed by Microsoft
29. Apple Languages
Swift
✘ Scala...brought to you by Apple
I kid! I kid!
✘ FP alternative to Objective C
✘ Borrowed some constructs from C & Objective C
✘ Optional types
✘ Categories (i.e. type-classes)
30. Erlang Languages
Erlang
✘ Ideal for distributed systems
✘ Fault-tolerant, real-time
✘ Highly-available systems
✘ BEAM virtual machine
Elixir
✘ Higher abstractions on top of Erlang
Reduces boilerplate
✘ Runs on BEAM
✘ New language but closely related to Erlang
31. Purist Languages
Haskell
✘ Purely functional
✘ Named after Haskell Curry
✘ Strong type system
✘ Introduced type-classes
✘ Strict immutability
Elm
✘ FP for the web
✘ Graphical layout without destructive updates
✘ Interops with (not compiles to) JavaScript/CSS/HTML
40. Function Has Side-Effects If It...
✘Modifies a variable
✘Modifies a data structure in place
e.g. append to linked list
✘Throws an exception
✘Prints to the console
✘Writes to a file
✘Updates a database
✘Draws to the screen
41. Function Has Side-Effects If It...
✘Modifies a variable
✘Modifies a data structure in place
e.g. append to linked list
✘Throws an exception
✘Prints to the console
✘Writes to a file
✘Updates a database
✘Draws to the screen Have you ever passed a
reference of a list to
something else?
44. Functional Imperative OOP
Pure functions are
easy to test
Local reasoning
In => Out
VS
Objects are hard to
test
Encapsulated state
Context
Global reasoning
45. Pure functions are
easy to re-use
Low risk
Little-to-no
dependencies
VS
We are terrible at
making truly reusable
objects
Challenges of tight
coupling
Hard to abstract at
correct level
Functional Imperative OOP
46. Pure functions are
easy to parallelize
State in isolation
Just lego pieces
VS
Sharing is cool in
life...not in threads
How many
concurrency patterns
do we need to deal
with shared state?
Functional Imperative OOP
47. Pure functions reduce
need for most OOP
design patterns
VS
‘Cause who doesn’t
want to know about
your
MVVMVMVMMVCCC
singleton factory
observer adapter
thingy?
Functional Imperative OOP
60. // Imagine how many combinations we can use this code
// Imagine how easy testing is
object Person {
def drink(coffee: Coffee): AwakePerson = ???
}
def wakeSomeone(makeIt: () => Coffee): AwakePerson = {
Person.drink(makeIt())
}
Anything that
makes coffee
62. // Which right triangle that has integers for all sides and all sides equal to
// or smaller than 10 has a perimeter of 24?
def rightTriangle: Seq[Int] =
for {
c <- 1 to 10
b <- 1 to c
a <- 1 to b
if ((Math.pow(a,2) + Math.pow(b,2) == Math.pow(c,2)) && (a + b + c == 24))
} yield (a, b, c)
rightTriangle
Answer: [6, 8, 10]
It’s Not About the How
but the What
78. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z = DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
79. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z = DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Yeah, I know
this is bad.
But you know
you’ve seen
this before.
Hang with me.
80. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z =
DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Pyramid
of Doom
81. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z =
DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Pyramid
of Doom
The Only
Lines Doing
Work
That’s only
20%!
82. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z =
DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Pyramid
of Doom
Look at all
those nulls!
Half this code
is null
checking.
Nulls are a
serious code
smell!
83. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z =
DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Pyramid
of Doom
Look at all
those nulls!
Half this code
is null
checking.
Nulls are a
serious code
smell!
Null Pointer
Exceptions
Waiting to
Happen
84. def foo(): Thing = {
val x = DoAThing()
if (x != null) {
val y = DoAnotherThing(x)
if (y != null) {
val z =
DoYetAnotherThing(y)
if (z != null) {
return z
} else {
return null
}
} else {
return null
}
} else {
return null
}
}
Pyramid
of Doom
Throw in async
operations, we can
create the same
pyramid with nested
callbacks.
103. State
You can do collection things to monads
Operation creates new monad of same type but
new state
.map(...)
.flatMap(...)
.fold(...)
.filter(...)
.collect(...)
.head
104. State
If Monad is “empty”, applied functions are
ignored
.map(...)
.flatMap(...)
.fold(...)
.filter(...)
.collect(...)
.head
105. def foo(): Option[Int] = Some(100)
val myFoo = foo()
val result =
myFoo
.map(i => i + 100)
.map(i => i.toString)
.map(i => i + " is a bigger number")
.getOrElse("didn't do anything")
// result = "200 is a bigger number"
106. def foo(): Option[Int] = None
val myFoo = foo()
val result =
myFoo
.map(i => i + 100)
.map(i => i.toString)
.map(i => i + " is a bigger number")
.getOrElse("didn't do anything")
// result = "didn’t do anything"
Executed but
not applied
107. Monads are so much
more but let’s keep it
simple for now…
...another talk to come
Good morning. My name is Jordan. I’m a software engineer for a company in OKC called “Oseberg” where I lead the Data Platform team. We use a lot of FP at Oseberg. In fact, all of our server-side code is FP using a language called Scala.
How many of you have used functional programming professionally? As a hobby? A strict functional programming language?
Get a raise of hands for who has done functional programming before.
Describe the paradigm phases over the years (procedural => oop => functional)
Fascination of video games as child (not necessarily gaming itself but the building aspect)
Story of dad buying my first programming book (show next slide with QBasic book)
I read this book cover-to-cover. Was fascinated. Felt like I knew a secret code or language that few others knew. I think that is a feeling many of us in this room probably felt at one time or another. The love of the tinkering. The love of the hacking around. The love of building something out of logic. Infinite loops, beeping ASCII codes, etc.
When we first learn programming, we are concerned about syntax. How do I enter the correct codes, symbols, and keywords to appease the wrath of the compiler and have our little code run?
Next, we are concerned with how to model things. What is the best way to represent this logical concept in the real world?
Next, how do we have our models interact with each other?
Next, how do we work in a team with other people writing code?
Next, how do we have systems talk to each other?
…
The further we go, the more evolved the problems we are solving. In today’s world, we now find ourselves processing Big Data. Massive volumes of data, many CPU cores, distributed computing clusters, and a high degree of parallelism. The problems we are solving today are not the problems we were solving yesterday.
That is why our field is about the pursuit of building. We are builders first and technologists second. How do we build things? And this means we should always be learning how to build in new ways.
Ask the audience.
Ask the audience.
Ask the audience.
Now this doesn’t mean we don’t have to learn new terminology. When we learned algebra, we could no longer constrain ourselves to basic addition and subtraction. Had to learn new phrases. When we learned OOP, we had to learn about classes, objects, encapsulation, inheritance, etc. New lingo for different techniques. Same with FP. You are going to have to learn about referential integrity, functors, monoids, monads, typeclasses, etc.
What if in algebra class your teacher docked you points because in reality, usage of ‘x’ mutated its state so that it wasn’t constant within the use of the function f() and the answer changes? You’d cry fowl! But don’t we do this kind of stuff all the time? When we were first becoming programmers, this is the kind of habits we were taught. Changing state.
What if in algebra class your teacher docked you points because in reality, usage of ‘x’ mutated its state so that it wasn’t constant within the use of the function f() and the answer changes? You’d cry fowl! But don’t we do this kind of stuff all the time? When we were first becoming programmers, this is the kind of habits we were taught. Changing state.
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?
Will this work for all inputs? How might we code this up?