Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Poor man’s FP
How to change your java
code in a way you never
thought about
Dmitry Lebedev
• WILDCARD conf
• AIESEC/Lotus conf
Functional Programming
• Higher order functions
• Pure functions
• Recursion
• Non-strict evaluation
• Currying
Higher order functions
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ", &foo)
Pure Functions
foo = Proc.new { |x| x*x+(x+20) }
Recursion
def fib(n)
return n if (0..1).include? n
fib(n-1) + fib(n-2) if n > 1
end
Non-strict evaluation
print length([2+1, 3*2, 1/0, 5-4])
Currying
plus = lambda {|a,b| a + b}
plus.(3,5) #=> 8
plus_one = plus.curry.(1)
plus_one.(5) #=> 6
plus_one.(11) #=> 12
Java 8?
import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Java8 {
public static void main(String[] args) {
Button myButton = new Button();
myButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println(ae.getSource());
}
});
}
}
Java 8?
import java.awt.Button;
import java.awt.event.ActionEvent;
public class Java8 {
public static void main(String[] args) {
Button myButton = new Button();
myButton.addActionListener((ActionEvent ae) -> {
System.out.println(ae.getSource());
});
}
}
Java 8?
import java.awt.Button;
public class Java8 {
public static void main(String[] args) {
Button myButton = new Button();
myButton.addActionListener(ae ->
{System.out.println(ae.getSource());}
);
}
}
Still living under Java 6?
Languages
• Scala
• Clojure
Libraries
• Guava
• LambdaJ
• Functional Java
Guava
• Function<A, B>, which has the single method B
apply(A input). Instances of Function are
generally expected to be referentially transparent -- no
side effects -- and to be consistent with equals, that
is, a.equals(b) implies that
function.apply(a).equals(function.app
ly(b)).
• Predicate<T>, which has the single method
boolean apply(T input). Instances of
Predicate are generally expected to be side-effect-free
and consistent with equals.
Guava
List converted = ImmutableList.copyOf(
Iterables.transform( userDTOs, new Function(){
public User apply( UserDTO input ){
return new User( input.name, input.id );
}
}));
LambdaJ
Person me = new Person("Mario", "Fusco", 35);
Person luca = new Person("Luca", "Marrocco", 29);
Person biagio = new Person("Biagio", "Beatrice", 39);
Person celestino = new Person("Celestino", "Bellone", 29);
List<Person> meAndMyFriends =
asList(me, luca, biagio, celestino);
List<Person> oldFriends =
filter(having(on(Person.class).getAge(), greaterThan(30)),
meAndMyFriends);
FunctionalJava
import fj.data.Array;
import static fj.data.Array.array;
import static fj.Show.arrayShow;
import static fj.Show.intShow;
import static fj.function.Integers.even;
public final class Array_filter {
public static void main(final String[] args) {
final Array<Integer> a = array(97, 44, 67, 3, 22, 90,
1, 77, 98, 1078, 6, 64, 6, 79, 42);
final Array<Integer> b = a.filter(even);
arrayShow(intShow).println(b);
// {44,22,90,98,1078,6,64,6,42}
}
}
Invention of Own Bicycle
First Attempt
public static <T> void forEach(Collection<T> list,
Procedure<T> proc) {
for (T object : list) {
proc.invoke(object);
}
}
Another try
public static <T, E> Collection<E> each(Collection<T>
list, Function<T, E> function) {
ArrayList<E> result = new ArrayList<E>();
for (T object : list) {
result.add(function.apply(object));
}
return result;
}
Use Case
result.addAll(
each(
imageList,
new Function<S3ObjectSummary, String>({
@Override
public String apply(@Nullable
S3ObjectSummary input) {
return siteURL + input.getKey();
}
}
));
Let’s complicate!
public interface MapFunction<T, K, V> {
Pair<K,V> proceed(T key);
}
Let’s complicate!
public static <T, K, V> Map<K, V>
map(Collection<T> list,
MapFunction<T, K, V> function) {
Map<K, V> result = new HashMap<K, V>();
for (T object : list) {
Pair<K, V> pair =
function.proceed(object);
result.put(pair.getKey(),
pair.getValue());
}
return result;
}
Let’s complicate!
...
List<Future> fs = new
ArrayList<Future>(list.size());
for (final T object : list) {
fs.add(exec.submit(new Callable() {
@Override
public Object call() throws Exception {
return function.proceed(object);
}
}));
}
...
Let’s complicate!
...
for (Future ft : fs) {
Pair<K, V> pair = (Pair<K, V>) ft.get();
result.put(pair.getKey(), pair.getValue());
}
...
Question?
The End

More Related Content

Poor Man's Functional Programming

  • 1. Poor man’s FP How to change your java code in a way you never thought about
  • 2. Dmitry Lebedev • WILDCARD conf • AIESEC/Lotus conf
  • 3. Functional Programming • Higher order functions • Pure functions • Recursion • Non-strict evaluation • Currying
  • 4. Higher order functions foo = Proc.new { |prompt| prompt.echo = false } new_pass = ask("Enter your new password: ", &foo)
  • 5. Pure Functions foo = Proc.new { |x| x*x+(x+20) }
  • 6. Recursion def fib(n) return n if (0..1).include? n fib(n-1) + fib(n-2) if n > 1 end
  • 8. Currying plus = lambda {|a,b| a + b} plus.(3,5) #=> 8 plus_one = plus.curry.(1) plus_one.(5) #=> 6 plus_one.(11) #=> 12
  • 9. Java 8? import java.awt.Button; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Java8 { public static void main(String[] args) { Button myButton = new Button(); myButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.out.println(ae.getSource()); } }); } }
  • 10. Java 8? import java.awt.Button; import java.awt.event.ActionEvent; public class Java8 { public static void main(String[] args) { Button myButton = new Button(); myButton.addActionListener((ActionEvent ae) -> { System.out.println(ae.getSource()); }); } }
  • 11. Java 8? import java.awt.Button; public class Java8 { public static void main(String[] args) { Button myButton = new Button(); myButton.addActionListener(ae -> {System.out.println(ae.getSource());} ); } }
  • 12. Still living under Java 6? Languages • Scala • Clojure Libraries • Guava • LambdaJ • Functional Java
  • 13. Guava • Function<A, B>, which has the single method B apply(A input). Instances of Function are generally expected to be referentially transparent -- no side effects -- and to be consistent with equals, that is, a.equals(b) implies that function.apply(a).equals(function.app ly(b)). • Predicate<T>, which has the single method boolean apply(T input). Instances of Predicate are generally expected to be side-effect-free and consistent with equals.
  • 14. Guava List converted = ImmutableList.copyOf( Iterables.transform( userDTOs, new Function(){ public User apply( UserDTO input ){ return new User( input.name, input.id ); } }));
  • 15. LambdaJ Person me = new Person("Mario", "Fusco", 35); Person luca = new Person("Luca", "Marrocco", 29); Person biagio = new Person("Biagio", "Beatrice", 39); Person celestino = new Person("Celestino", "Bellone", 29); List<Person> meAndMyFriends = asList(me, luca, biagio, celestino); List<Person> oldFriends = filter(having(on(Person.class).getAge(), greaterThan(30)), meAndMyFriends);
  • 16. FunctionalJava import fj.data.Array; import static fj.data.Array.array; import static fj.Show.arrayShow; import static fj.Show.intShow; import static fj.function.Integers.even; public final class Array_filter { public static void main(final String[] args) { final Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final Array<Integer> b = a.filter(even); arrayShow(intShow).println(b); // {44,22,90,98,1078,6,64,6,42} } }
  • 17. Invention of Own Bicycle
  • 18. First Attempt public static <T> void forEach(Collection<T> list, Procedure<T> proc) { for (T object : list) { proc.invoke(object); } }
  • 19. Another try public static <T, E> Collection<E> each(Collection<T> list, Function<T, E> function) { ArrayList<E> result = new ArrayList<E>(); for (T object : list) { result.add(function.apply(object)); } return result; }
  • 20. Use Case result.addAll( each( imageList, new Function<S3ObjectSummary, String>({ @Override public String apply(@Nullable S3ObjectSummary input) { return siteURL + input.getKey(); } } ));
  • 21. Let’s complicate! public interface MapFunction<T, K, V> { Pair<K,V> proceed(T key); }
  • 22. Let’s complicate! public static <T, K, V> Map<K, V> map(Collection<T> list, MapFunction<T, K, V> function) { Map<K, V> result = new HashMap<K, V>(); for (T object : list) { Pair<K, V> pair = function.proceed(object); result.put(pair.getKey(), pair.getValue()); } return result; }
  • 23. Let’s complicate! ... List<Future> fs = new ArrayList<Future>(list.size()); for (final T object : list) { fs.add(exec.submit(new Callable() { @Override public Object call() throws Exception { return function.proceed(object); } })); } ...
  • 24. Let’s complicate! ... for (Future ft : fs) { Pair<K, V> pair = (Pair<K, V>) ft.get(); result.put(pair.getKey(), pair.getValue()); } ...

Editor's Notes

  1. Functions are higher-order when they can take other functions as arguments, and return them as results.
  2. Pure functions support the mathematical definition of a function:y = f(x)Which means:1- A function should return the same exact value given the same exact input.2- A function does one thing exactly(has one clear mission), it has no side effects like changing some other value or write to stream or any other mission rather than its assigned one.In fact Ruby doesn’t force you to write pure functions, but certainly it helps you to do so. Actually exercising yourself to write in pure functional style when possible helps you really in many ways:1- It makes your code clean, readable and self-documenting.2- It makes your code more “thread safe”3- It helps you more when it comes to TDD.
  3. Iteration (looping) in functional languages is usually accomplished via recursion.
  4. Higher-order functions enable Currying, which the ability to take a function that accepts n parameters and turns it into a composition of n functions each of them take 1 parameter. A direct use of currying is the Partial Functions where if you have a function that accepts n parameters then you can generate from it one of more functions with some parameter values already filled in.