OOP => FP mindshift
The foundation of Functional Programming
Dawid Furman
> Welcome and thanks for all attenders
> Thanks for the invitation - Jan and Phillip
> A little about Malaga Scala Developers
> Big conferences in Andalucia - J on the Beach Malaga, Lambda World Cadiz
Perception and imagination
Reflexion about the programming paradigms
The way of thinking about real or abstract
entities
their relationships
and communications
each other to build
Types =>
Object =>
Relationships =>
Communications =>
Application Bounded Context
> The syntax is not on the main stage
> The syntax is a tool for realize our percetions and thinking about the code
> This mindset creates our imagination about the implementation of the rules.
> This mindset create and restrictions and some kind of the border of the World
The Anonymous function powered by
λ
The λ allows us dynamically create:
1. functions
2. scope (lexical scope)
Nil. Milstone: The lambda function.
> E: Sygnature of the method
> E: Lexical scope (i : Int) => {val y = 5; (a: Int) => i + y + a}
> E: the difference between functions and method
> Being able to use unname functions to create scope on the flay is an essential tool
for doing much more powerful stuff.
Methods => Functions
I. Milstone: Methods are NOT Functions.
> E: All we know methods from OOP - encapsulate an bahavior for the object
> E: Having an references to lamba functions is very important characteristic
> E: The difference between functions and method
> E: The operator _
> Q: What about procedure?
Functions => First class functions
A functions that can be: 1. passed or 2. returned as any other data.
> E: Functions that can be passed and return like any other values.
> E: No sides effects - IO etc.
> E: For the same arguments return alwasy the same values.
Higher order functions
Another fancy and cool name
Is a function that can take as a argument:
function/s
(and | or)
return a function.
Extract the computation - sounds like good old practices Divide & Conquer and DRY.
II. Milstone: Higher and first class function.
> E: Functions that can be passed and return like any other values.
> E: Together with first class function allow us extract the computation.
> Q: What is the type of that function: (Int => Int, Int) => Int
> Q: And the other two functions are: Int => Int
> E: (1 to 10) map ((x: Int) => x * 2)
Closures and Partial Application
Enclose a first class functions inside the lambda function.
III. Understanding Partial Application.
> E: Show where the fucntion is seeded.
> E: When you capture a value inside a lambda functions, this is referred to as a closure
> E: Invoking the function with fewer parameter returns an function
which is waiting for the rest paramters.
Partial Application - give a second thought
result = f(x)(y)(z)
<=>
f1 = f(x) =>
f2 = f1(y) =>
f2(z) = result
Currying make multiple parameter group real!
Currying
in context of Partial Application
IV. Partial Application as a tool for a functions pipelines/chain
map, filter, fold/l/r - What they have in common?
Anybody???
¡Recursion!
These Higher Order Functions abstracts away common patterns of recursion.
def filter(p: Int => Boolean): List[Int]
def map[B](f: Int => B): scala.collection.TraversableOnce[B]
def fold[A1 >: Int](z: A1)(op: (A1, A1) => A1): A1
> E: See these construct in REPL
> Q: Who like recursion ?
> E: Why recursion is better then iteration - while - foreach
> E: Avoid state chaning, local variables.
Part I => Checkpoint
=> lambda and lexical scope
=> first class functions
=> higher order functions
=> partial application, currying, closures
=> function composition
> E: (a:A) => f(g(a))
> Q: Why function composition is so important? get rid of all local mutable values
that are potential source of most of the errors.
Part II
Functional domain modeling
Data structures just are. They don`t do anything.
Joe Armstrong, Erlang creator.
Before immutablity...
Referencial transparency is a consequence of having pure functions.
Pure functions never ever changing state/s.
so no unexpected sides effects.
def pureFunction(oldState: A) : A = {
// no external references
A(a) // new object <=> represent state changing.
}
> Q: What is A(a) - new state
> Q: How we can recognize impure method signature?
> E: We can call this state changing - update it by copy
> E: Define good and bad state
Data modeling OOP vs. FP approach
OOP <=> encapsulate/couples state and behaviour
// Java POJO - Mutable data structure
class Status{
private int code;
private String statusMessage;
}
// Scala POJO
class Status (var code: Int, var statusMessage: String)
FP <=> decouple them.
// ADT - Product Type - as a immutable data structure
case class Status(code: Int, statusMessage: String)
"Good OOP is nothing more then FP in disguise."
"Design patterns are for fill the gap of the OOP abstractions lack."
"With the power paradigm you don`t need any framework for DI."
"In FP it is a common practice to compose and build computation pipelines
and defere evaluation until the end."
But... Where IS the power of FP that we talk about?!
> E: Sorry for that - but there is no single answer for that!
Everything is around Context!
The comprehension of for-comprehension expression
// This signature is only for the List
def flatMap[B](f: Int => List[B]): List[B]
III. Milstone: For-comprehension - a syntactic sugar for combination flatMap(s)/map together in a readable form.
> Q: Is not it tedious? IT IS!
> E:
val result = for {
a <- aSomeValueA
b <- aSomeValueB
} yield a + b
> E: Discussion about Option, Future
Putting it all together
DI in a functional way
¡doItHereTogether!
Last. Milstone:
For-Comprehension
> E: You know Spring, right?
> E: So this is one of the power of FP.
> E: trait Travel
> E: trait Repository[IdType, A]
> E: trait TravelRespository extends Repository[String, Travel]
> E: class TravelRposiotryArangoDB extends TravelRepository
> E: trait TravelService[Travel]{
def createTravelRequest (from: String, to: String) : Option[Travel]
> E: object TravelServiceLiftedImp extends TravelServiceLifted[Travel]
case class Reader[E, A](run: E => A) {
def map[B](f: A => B): Reader[E, B] = Reader(r => f(run(r)))
def flatMap[B](f: A => Reader[E, B]): Reader[E, B] = Reader(r => f(run(r)).run(r))
}
> E: Lifting to Function1[_,_]
Checkpoint Part II
=> OOP Application is a squence of statmens written in imperative way
where each statments is changing the program state.
=> FP is a sequence of exrepssion written in declarative way
where each expression represent a chain of transfromation without any chunks of mutability
that could provoke hidden state change.
More and more about FP
=> Pattern Matching - power of the types
=> Type classes vs. Interfaces
=> Kinds - as a labels for the types
Scala -> Haskell
References
¡Danke Sehr!
¿Fragen?