functional-reactive
Made in the European Union

Transformations

Curry, uncurry, compose and reshape โ€” utilities for working with functions as values.

com.svenruppert.functional.Transformations is a static utility class that collects everything you wish was on Function itself.

Currying & uncurrying

Most useful when memoizing multi-arg functions or building configurable factories.

// BiFunction <-> Function<A, Function<B, R>>
<A, B, R> Function<BiFunction<A, B, R>, Function<A, Function<B, R>>>             curryBiFunction();
<A, B, R> Function<Function<A, Function<B, R>>, BiFunction<A, B, R>>             unCurryBiFunction();

// TriFunction <-> Function<A, Function<B, Function<C, R>>>
<A, B, C, R> Function<TriFunction<A, B, C, R>, Function<A, Function<B, Function<C, R>>>>
                                                                                  curryTriFunction();
<A, B, C, R> Function<Function<A, Function<B, Function<C, R>>>, TriFunction<A, B, C, R>>
                                                                                  unCurryTriFunction();

// Same pairs for Checked* variants
curryCheckedBiFunction()   unCurryCheckedBiFunction()
curryCheckedTriFunction()  unCurryCheckedTriFunction()
BiFunction<Integer, Integer, Integer> add = Integer::sum;
Function<Integer, Function<Integer, Integer>> curried =
    Transformations.<Integer, Integer, Integer>curryBiFunction().apply(add);

curried.apply(2).apply(3);   // 5

Composition with explicit type info

Function.compose sometimes loses type inference when chained at the call site. higherCompose is the same operation but as a curried function value โ€” explicit type arguments fix it:

<T, U, V> Function<Function<U, V>, Function<Function<T, U>, Function<T, V>>> higherCompose();
Function<Integer, Integer> fx =
    Transformations.<Integer, Integer, Integer>higherCompose()
        .apply((Integer x) -> x + 2)
        .apply((Integer x) -> x * 2);

fx.apply(3);   // ((3*2)+2) = 8

Casting helpers โ€” assign a lambda to its target type

These helpers exist purely so you can hand a lambda to the compiler with an explicit target type, without writing the cast inline. Useful when type inference fails or when you want a one-liner local variable:

<T>     Predicate<T>          asPredicate(Predicate<T> p);
<T>     Consumer<T>           asConsumer(Consumer<T> c);
<T>     Supplier<T>           asSupplier(Supplier<T> s);
<T, R>  Function<T, R>        asFunc(Function<T, R> f);
<T, R>  CheckedFunction<T, R> asCheckedFunc(Function<T, R> f);
var print = Transformations.<String>asConsumer(System.out::println);
var parse = Transformations.<String, Integer>asCheckedFunc(Integer::parseInt);

Stream sources

<T> Function<Iterator<T>,    Stream<T>> iteratorToStream();
<T> Function<Enumeration<T>, Stream<T>> enumToStream();

Bridge non-Stream iteration APIs (e.g. ResultSet, JNDI enumerations, JDK 8 Iterators) into a Stream:

Stream<Locale> locales =
    Transformations.<Locale>enumToStream().apply(someEnumeration);

Predicate negation

Function<Boolean, Boolean> not();
<T> Predicate<T>           not(Predicate<T> p);
list.stream()
    .filter(Transformations.not(String::isEmpty))
    .forEach(System.out::println);