7. • A programming paradigm where
functions are first-class entities
• The main concepts are:
1. programming with functions
2. avoid mutation
• A new way of thinking
WHAT IS FP ?
8. • Object Immutability
• Functions:
– as first class citizens
– no side effects (Pure functions)
– Higher Order Functions
• No loops
• Lazy evaluation
WHAT IS FP ? / FUNCTIONAL PRINCIPLES
9. • Easier parallelization
• Less code
• Easy testing
• Results instead of steps
• Easy to understand code
WHAT IS FP ? / WHAT YOU GET ?
12. An immutable object is an object
whose state cannot be modified
after it is created
IMMUTABLE OBJECTS
13. “Classes should be immutable unless
there’s very good reason to make them
mutable… If a class cannot be made
immutable, limit its mutability as much
as possible”
Joshua Bloch
IMMUTABLE OBJECTS
30. •Allows easy parallelism
•Encourages abstraction
•Reusing of common code
•Isolates the essential parts
•Allows easier unit testing
HIGHER ORDER FUNCTIONS
35. HIGHER ORDER FUNCTIONS / LAMBDA EXPRESSIONS
• A lambda expression is an anonymous
method
• Lambdas favor HOFs
• more powerful libraries
• more expressive, more readable, less
error-prone use code
• Boosts developer productivity
• key to an accessible parallelism strategy
44. A function is said to be pure if
1. it returns same set of values
for same set of inputs
2. It does not have any
observable side effects
PURE FUNCTIONS / DEFINITION
47. Impure functions / Side effects :
1. Alter parameters passed by ref
2. Alter members of passed
objects
3. Alter external objects
PURE FUNCTIONS / SIDE EFFECTS
68. NO LOOPS / FUNCTION CHAINING
• Similar to unix pipes :
ps -ax | tee processes.txt | more
• Already used in java in fluent interfaces
• Eliminate the need for intermediate variables
69. NO LOOPS / FUNCTION CHAINING
persons.stream()
.filter(e -> e.getGender() == Person.Sex.MALE)
.forEach(e -> System.out.println(e.getName()));
for (Person p : persons) {
if (p.getGender() == Person.Sex.MALE) {
System.out.println(p.getName());
}
}
70. NO LOOPS / AGGREGATE OPERATIONS
• They use internal iteration
• They process elements from a stream
• They support behavior as parameters
76. FUNCTIONS CHAINING / STREAMS IN JAVA 8
• Streams do not provide a means to directly access or
manipulate their elements
• are concerned with declaratively describing the
computational operations which will be performed in
aggregate on that source
• No storage: they carry values from a source through a
pipeline
• Functional in nature ( operations do not modify its
underlying data)
• Operations can be implemented lazily ( for single pass
execution & efficient implementation of short-circuit
operations)
• No bounds : streams can be infinite
86. OPTIONAL / NULL, THE BILLION DOLLAR MISTAKE
"I call it my billion-dollar mistake. It was the invention of the
null reference in 1965. […]
I couldn't resist the temptation to put in a null reference,
simply because it was so easy to implement.
This has led to innumerable errors, vulnerabilities, and system
crashes, which have probably caused a billion dollars of pain
and damage in the last forty years“
Tony Hoare
87. OPTIONAL / THE SOLUTION TO NULL
java.util.Optional<T> :
• A class that encapsulates an optional value
• A single-value container that either contains
a value or doesn't (empty)
Ce ne propunem ?
Prezentarea este destul de ambitioasa pentru ca ataca doua tinte: functional programming si java8 most important features.
Focusul va fi pe FP.
Disclaimer:
- codul in F#
The evolution of the clock speed over time.
Unul din factorii care contribuiau la imbunatatirea puterii de calcul si-a oprit cresterea.
Este prima data cand legea lui Moore este pusa sub semnul intrebarii.
Hardware-ul se schimba -> software-ul tre’ sa se schimbe pentru a tine pasul.
Articol: The free lunch is over :
- processor manufacturers will focus on products that better support multithreading (such as multi-core processors)
- software developers will be forced to develop massively multithreaded programs as a way to better use such processors
(i.e: proasta calitate a codului, nu mai poate fi acoperita de imbunatatirea vitezei de calcul)
Codul nostru va rula distribuit intre core-urile procesorului.
Evolutia limbajelor de programare.
A se nota faptul ca limbajele functionale au aparut cu mult inaintea limbajelor OOP.
Principiile din limbajele functionale se mapeaza mult mai bine pe ideea de multi threading / paralelism.
Principiile FP derivate din cele doua concepte prezentate anterior
Easier parallelization != No work for parallelization
Results instead of steps -> SQL
Verbe in locul substantivelor
Imutabilitatea nu e ceva nou.
Este recomandata si-n OOP.
No setters
Final fields
Final class
Java examples ?
Un exemplu mai complex.
Unul din campurile clasei este mutabil.
Ultima metoda returneaza o copie defensiva pentru a evita mutabilitatea.
Exemplu de clasa imutabila in Scala.
Exemplu de clasa imutabila in F#.
Pentru a face un obiect mutabil trebuie utilizat cuvantul cheie “mutable”
Talk about the memory consumption and the extra work to be done by the garbage collector.
Extrapolate the example above to lists, trees, etc.
Other benefits:
- don't need a copy constructor
- don't need an implementation of clone
- allow hashCode to use lazy initialization, and to cache its return value
- don't need to be copied defensively when used as a field
- make good Map keys and Set elements (these objects must not change state while in the collection)
- always have "failure atomicity" : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state
In loc de obiectul rational de mai devreme sa ne gandim ca avem o lista.add
Garbage collection: ok atata timp cat nu lucrezi la Twitter.
This cannot be achieved in Java but … talk about the new functional interfaces ; Predicate, Filter, …
HOFs can be assigned to variables
HOFs can be created at runtime and used
Functions are just as any other data types
Sum accepts another function as input parameter
higherOrderFunction returns a function as a result
Functions as first class citizens
Functions as parameters
Functions as return values
sumOfSquares -> easy abstraction –> sum (f)
Easy parallelism
A new package added in java8
In java everything is a class -> functions are classes
The most important java classes in the java.util.function package
All introduced in Java8
Cam asa am fi utilizat clasele in Java 7
Note the lambda expression
No boilerplate
Explain the type inference
Remember the anonymous classes in java
Examples with the most important classes implemented as lambda expressions
Cum acoperim toate situatiile ? Prin annotation : FunctionalInterface
A functional interface has only one abstract method.
Instances of functional interfaces can be created with lambda or method references
This is how we use the Functional Interface annotation.
Note: the lambda expression used to define an anonymous definition of a Functional Interface
Cum utilizam metodele deja existente ?
De observat referintele la metodele din clasele Math, Integer.
HOF
Lambda
Function references
Pure functions = No side effects
Impure function - has side effects
Impure function -> it doesn’t return the same values for the same inputs
Sin = pure
Length = pure
Random() = impure
Println() = impure
SQL Insert = impure
Easier to maintain: devs spend less time analyzing the impact
Once tested all edge conditions we can be sure that the function behaves correctly
Easy concurency: see next side/example
No side effects favorizeaza paralelismul
The same input -> same output favorizeaza testarea si intelegerea
Any write to the console is a side-effect.
Database updates or file writes on disk is a side-effect.
So we cannot be 100% pure but the goal is to be as pure as possible.
In an input – process– output flow the goal is to keep the middle (process) functional.
g o f (c) = #
Metodele compose si andThen
Pure functions
Function composition
HOF
Lambdas
Function references
What is the problem ?
Incurajeaza shared state (variabilele partajate) = nu bine pt. paralelism
Mult boilerplate
Why avoid loops ?
boilerplate code
Incurajeaza partajarea state-ului deci nu este prietenos cu multi-threadingul.
In some cases ( most of them ? ) recursion is more intuitive then iteration.
Functional languages have better implementations for recursion
For OOP languages iteration is much faster than recursion
The mantra of functional languages: CLARITY TRUMPS EFFICIENCY (preferam claritatea vs. eficienta)
the function’s stack frame can be reused.
Remember stiva de executie a unei functii.
After the call to factorial(n-1) there is still work to be done => not a tail recursive action
Note: Since the stack trace is optimized, when printing the stack trace one will only see the last call instead of the entire stack trace.
Functional languages have better support for recursion (see the list.head, list.tail)
This is not possible with all lists in idiomatic java.
Function chaining = Un caz particular de compozitie
To be discussed here:
Imperative approach vs. Functional approach :
For vs. map-reduce
State vs. stateless
Discussion about state / share state ( in a multi-threaded env.) : let’s sum the salaries of males in a multi-threaded env.
Func. Chaining can be seen as a particular case of composition.
Discussion about state / share state ( in a multi-threaded env.) : let’s sum the salaries of males in a multi-threaded env.
Func. Chaining can be seen as a particular case of composition.
Note the chaining of combinator methods : map, filter, reduce/foldLeft
The same functionality in Java8.
Imperative vs. Declarative style / Ce face functia vs. Cum face functia / The SQL Example.
Note 1: the stream() method
Note 2: a method added to a the list interface (DEFAULT METHODS discussion)
Discussion about map/filter/reduce
We’ll come back to map/reduce/filter in a few moments
The average age of males in the persons list.
When using streams we need the following components:
1 A source ( list )
2.Zero or more intermediate operations ( filters, transformers)
3. A terminal operation ( average)
Default Method Discussion
2. Stream interface
The Stream interface and the map / reduce methods
Streams cannot be reused.
Please check the Stream javadoc .
http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps
The stream could have been infinite
I could have used only lambdas
Note the findFirst method returning an optional (discussed later in this material)
Re-start the map/reduce discussion
Reduce needs to be associative
(a+b)+c = a+(b+c), i.e. the order in which the additions are performed doesn't matter.
How sequential reduce works.
Free parallelism but this doesn’t happen every time
Sum() is a particular form of reduce() – a shortcut for reduce(0, (a,b) -> a+b)
reduce, collect, sum = terminal methods
Note: Order of filtering matters
Note: the operation has to be associative otherwise the result will not be consistent (no compilation or runtime error)
Example of a non associative operation: x*x + y*y
Discussion about non-associative
Disclaimer: the table shows the test results in ideal conditions ( no other threads were running) - in production systems you won’t get this kind of difference
The power of collectors
The problem with null: Depending on the context, null means “no value”, other times it means “error” or “nothing”, but it can even mean “success”
Optional is inspired from Haskel and Scala
Idiot proof : It forces you to actively think about the absent case if you want your program to compile
There are three ways to deal with the absence of a value in an Optional: to provide a substitute value, to call a function to provide a substitute value, or to throw an exception
Functional programming = no loops
Recursivitate
Function chaining
Function composition
Streams
Map / reduce
Default methods
Optional
Functional programming = no loops
Recursivitate
Function chaining ( this is also related to composition)
Streams
Map / reduce
Lambda instead of a Runnable
Runnable este o interfata functionala
Lambda instead of an Action Listener
Lambda instead of a Comparator.
Why the Users type has been specified ? - where is the type inference ?
Method reference in a forEach method
BufferedReader.lines() returns a Stream
Files.lines() returns a Stream as well. The examples shows how to use the stream in a try-with-resources ( it implements AutoClosable).
Spring jdbc template with lambda expressions ( instead of RowMapper.mapRow(ResultSet, int rowNum)
Outside the scope :
Advanced Laziness
Monads
Function currying
Outside the scope :
Java8
------------------------------------
Type Annotations
Date and time API
Lambda translation to bytecode
Nashorn Javascript engine
Easier parallelization != No work for parallelization
What instead of How
Verbe in loc de substantive
Some non-programming mistakes have been intentionally inserted into the presentation
Responsive: The system responds in a timely manner
Resilient: The system stays responsive even in failure
Elastic: The service allocates resources as needed ( according to the workload)
Message Driven: Async message passing for loose coupling, isolation, transparency