Functional Concepts
a Java simulation
This article is a follow up to the one about functional concepts, suggested by @pcolomb. As I’m not yet fully aware of Java 8 lambda to add snippets, I decided to present a way to simulate these concepts in pure Java.
The proposed version is not really usable, and probably performs badly, but can help to understand the underlying concepts (and it’s fun).
Lambda ¶
As explained in the previous article, lambda are anonymous functions, that can be created on demand. We’ll create a class that simulate an unary function.
We thus need to create a generic class simulating anonymous
function creation, having A → B
as signature. This can be defined
as:
1 2 abstract class Function<A,R> { 3 public abstract R call(A arg); 4 } 5 6 class Lambda { 7 public static void main(String[] args) { 8 9 Function<Integer,Integer> doubler = new Function<Integer,Integer>(){ 10 public Integer call(Integer arg) { return 2*arg; }}; 11 12 System.out.println(doubler.call(21)); 13 } 14 }
It works! To better integrate this, it would be nice that the
“function” implements Callable
, which would allow to use it in a
context needing this interface. Let’s try to modify our class accordingly.
Since the argument can’t be given to call
, we must keep it in the
object’s internal state, as a private attribute.
Callable
lambda (LambdaCallable.java)1 import java.util.concurrent.Callable; 2 3 class NotBoundFunctionException extends Exception { } 4 5 abstract class Function<A,R> implements Callable<R> { 6 private A _arg; 7 public A arg() { return this._arg;} 8 public void arg(A arg) { this._arg = arg; } 9 10 public Function() {} 11 public Function(A arg) { this.arg(arg); } 12 13 public Function<A,R> bind(A arg) { this.arg(arg); return this; } 14 15 protected abstract R callMe(); 16 public R call() throws Exception { 17 if ( this._arg == null) { throw new NotBoundFunctionException(); } 18 return this.callMe(); 19 } 20 public R call(A arg) throws Exception { 21 return this.bind(arg).call(); 22 } 23 } 24 25 class LambdaCallable { 26 public static void main(String[] args) { 27 28 Function<Integer,Integer> doubler = new Function<Integer,Integer>(){ 29 protected Integer callMe() { return 2*this.arg(); }}; 30 31 try { 32 33 doubler.arg(21); 34 System.out.println(doubler.call()); 35 36 System.out.println(doubler.bind(12).call()); 37 38 System.out.println(doubler.call(21)); 39 40 } catch (Exception e) { System.exit(1); } 41 } 42 }
Note the Function<A,R> bind(A arg)
method, having a
fluent interface flavour, allowing to easily chain methods. This
bind
method is equivalent to partialize the function,
that can therefore be called without arguments, and thus follow the
Callable
interface. This partial application corresponds to a
closure, the closed variable being kept in a function private attribute.
Finally, call
overloading makes the use of the function more
natural, keeping the interface compatibility at the same time (beware the
internal side effect, since the object state is changed).
We just thus simulated a closure allowing a partial application.
Polyadic Functions and Currying ¶
The Function
object gives us unary functions, which is
somewhat limited. How can we create functions with several arguments? We could
create a generic class for every arity, but there is a simpler solution: create
curryfied functions, that is a function of
just one argument, returning a function of just one argument, etc.
It is already possible “by hand”, with what we have. Let’s create a
function add: Interger → Integer → Integer
with our first lambda
version.
1 2 abstract class Function<A,R> { 3 public abstract R call(final A arg); 4 } 5 6 class Curry { 7 public static void main(String[] args) { 8 Function<Integer,Function<Integer,Integer>> add = new Function<Integer,Function<Integer,Integer>>(){ 9 public Function<Integer,Integer> call(final Integer a) { 10 return new Function<Integer,Integer>(){ 11 public Integer call(final Integer b) { 12 return a + b; 13 } 14 }; 15 } 16 }; 17 try { 18 System.out.println(add.call(21).call(21)); 19 20 Function<Integer,Integer> partialAdd = add.call(21); 21 System.out.println(partialAdd.call(21)); 22 23 } catch (Exception e) { System.exit(1); } 24 } 25 }
Not really readable, but it works. Note that arguments (at least
a
must be finals, since they are used in an anonymous inner class;
but hey, we are doing functional programming right?
On fait ici une « vrai » fermeture, au sens fonctionnel, puisque la variable
a
est bien capturée directement dans la définition de la fonction
interne ; mais notre fonction n’est plus Callable
. On est ici très
proche de la version Javascript de
curryfication simple.
This one is a “true” functional closure, since the a
variable is captured in the internal function definition; but this function is
no more Callable
. This approach is very similar to the Javascript one.
Let’s use our Callable
version of
Function
:
Callable
polyadic function by manual currying (CurryCallable.java)1 import java.util.concurrent.Callable; 2 class CurryCallable { 3 public static void main(String[] args) { 4 Function<Integer,Function<Integer,Integer>> add = new Function<Integer,Function<Integer,Integer>>() { 5 protected Function<Integer,Integer> callMe() { 6 final Integer first = this.arg(); 7 return new Function<Integer,Integer>(){ 8 private Integer curry = first; 9 protected Integer callMe() { 10 return this.arg() + curry; 11 } 12 }; 13 } 14 }; 15 try { 16 17 System.out.println(add.call(21).call(21)); 18 19 Function<Integer,Integer> partialAdd = add.call(21); 20 System.out.println(partialAdd.call(21)); 21 22 Callable<Integer> callableAdd = add.call(37).bind(1300); 23 System.out.println(callableAdd.call()); 24 25 } catch (Exception e) { System.exit(1); } 26 } 27 }
Ouch! It hurts, but it works, and with the previous features.
And what if we want both? The “ease” of function definition and the
greater flexibility? In object oriented paradigm, we would use
delegation, in functional programming, it’s called function
composition, but it’s the same principle. Let’s create a “function”
that takes a function and returns partial, augmented with the second approach
methods. It’s the decorator pattern from a functional point of view
(it’s the name used is Python world for such a thing). It’s the same approach,
but instead of redefining callMe
, we create a fun
attribute containing a function that will be called with the arg
value (thus the delegation).
Callable
polyadic function by composing (CurryComposed.java)1 import java.util.concurrent.Callable; 2 3 class NotBoundFunctionException extends Exception { } 4 class FunctionUndefinedException extends Exception { } 5 6 abstract class Function<A,R> { 7 public abstract R call(final A arg); 8 } 9 10 class CallableFunction<A,R> implements Callable<R> { 11 private A _arg; 12 public A arg() { return this._arg;} 13 public void arg(A arg) { this._arg = arg; } 14 15 private Function<A,R> _fun; 16 public Function<A,R> fun() { return this._fun; } 17 public void fun(Function<A,R> fun) { this._fun = fun; } 18 19 public CallableFunction() { } 20 public CallableFunction(A arg) { this.arg(arg); } 21 public CallableFunction(Function<A,R> fun) { this.fun(fun); } 22 public CallableFunction(Function<A,R> fun, A arg) { 23 this.fun(fun); 24 this.arg(arg); 25 } 26 27 public Callable<R> bind(A arg) { this.arg(arg); return this; } 28 29 public R call() throws Exception { 30 if ( this.arg() == null) { throw new NotBoundFunctionException(); } 31 if ( this.fun() == null) { throw new FunctionUndefinedException(); } 32 return this.fun().call(this.arg()); 33 } 34 public R call(A arg) throws Exception { 35 return this.bind(arg).call(); 36 } 37 } 38 39 40 class CurryComposed { 41 public static void main(String[] args) { 42 Function<Integer,Function<Integer,Integer>> add = new Function<Integer,Function<Integer,Integer>>(){ 43 public Function<Integer,Integer> call(final Integer a) { 44 return new Function<Integer,Integer>(){ 45 public Integer call(final Integer b) { 46 return a + b; 47 } 48 }; 49 } 50 }; 51 52 try { 53 54 System.out.println(add.call(21).call(21)); 55 56 Function<Integer,Integer> partialAdd = add.call(21); 57 System.out.println(partialAdd.call(21)); 58 59 CallableFunction<Integer,Integer> callableAdd = new CallableFunction<Integer,Integer>(partialAdd); 60 System.out.println(callableAdd.call(21)); 61 62 System.out.println(callableAdd.bind(1316).call()); 63 64 System.out.println((new CallableFunction<Integer,Integer>(add.call(668))).bind(669).call()); 65 66 } catch (Exception e) { System.exit(1); } 67 } 68 }