poor man's functional programming
TRANSCRIPT
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 > 1end
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) #=> 6plus_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.apply(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);
FunctionalJavaimport 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 Caseresult.addAll(
each(imageList, new Function<S3ObjectSummary, String>({
@Override
public String apply(@NullableS3ObjectSummary 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() {@Overridepublic 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