• Linas Naginionis
Software Craftsmanship

Currying in Java

Currying in Java

I’m all into functional programming nowadays. I’m learning new ways of thinking every day. I feel that thinking from functional perspective is very beneficial as it helps you to solve your problems in very elegant way. Of course, functional programming is not a silver bullet, there are some cases where better approaches are possible but overall it’s very strong paradigm with many benefits.

Currying and Java 8

If you practise or read about functional programming, you probably know what currying is. In short, currying transforms a multi-argument function so that it can be called in a chain of single-argument functions. Java doesn’t have currying built into the language but since we now have lambdas I thought it would be fun to try implementing it by myself.

After a few minutes it looks like it’s not so hard to do:

public class Currying {

    public static <T1, T2, R> Function<T2, R> curry(final BiFunction<T1, T2, R> function, final T1 arg) {
        return curry(function).apply(arg);
    }

    public static <T1, T2, R> Function<T1, Function<T2, R>> curry(final BiFunction<T1, T2, R> function) {
        return a -> b -> function.apply(a, b);
    }
}

And unit test:

@Test
public void when_Args_Strings_And_Returns_String_Currying_Gives_Correct_Value() throws Exception {
    BiFunction<String, String, String> concatStrings = (a, b) -> a + b;
    Function<String, String> intermediateFunc = curry(concatStrings, "Foo");
    assertEquals("FooBar", intermediateFunc.apply("Bar"));
    assertEquals("FooFoo", intermediateFunc.apply("Foo"));
}

You can see from this example that we are currying concatStrings function providing only single argument to it (“Foo”). Then we can reuse this function as many times as we want and apply different arguments. If you don’t want to provide argument for a curry function, we can use overloaded version. Then the test will look like this:

@Test
public void when_Args_Strings_And_Returns_String_Currying_Returns_Function_Only() throws Exception {
    BiFunction<String, String, String> concatStrings = (a, b) -> a + b;
    Function<String, Function<String, String>> intermediateFunc = curry(concatStrings);
    assertEquals("FooBar", intermediateFunc.apply("Foo").apply("Bar"));
    assertEquals("FooFoo", intermediateFunc.apply("Foo").apply("Foo"));
}

First version looks a bit better imo since we don’t need to declare our intermediate function like this:

Function<String, Function<String, String>>

Function Arguments

What if we have a function which expects more than two arguments?  Technically, there are no functions with more than one argument. We can always replace this function:

(a, b, c) -> d

with this one:

a -> b -> c -> d

So BiFunction is just a syntactic sugar to make our lives a little easier.

Final thoughts

In short, I think Java as a language is on the right path, it has gained a lot of power from all these features, borrowed from the functional languages. Now developers only need to start using these features and start thinking from the functional perspective more.

One thought on “Currying in Java

  1. Madhab Mahakud

    I already fall in love with functional programming. It will be great if you explain with real world example.
    I want to know where can we use for greater benefit ?

Leave a Reply

Your email address will not be published. Required fields are marked *

*