javaslang.CheckedFunction4 Maven / Gradle / Ivy
/* / \____ _ _ ____ ______ / \ ____ __ _______
* / / \/ \ / \/ \ / /\__\/ // \/ \ // /\__\ JΛVΛSLΛNG
* _/ / /\ \ \/ / /\ \\__\\ \ // /\ \ /\\/ \ /__\ \ Copyright 2014-2016 Javaslang, http://javaslang.io
* /___/\_/ \_/\____/\_/ \_/\__\/__/\__\_/ \_// \__/\_____/ Licensed under the Apache License, Version 2.0
*/
package javaslang;
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\
G E N E R A T O R C R A F T E D
\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javaslang.control.Option;
import javaslang.control.Try;
/**
* Represents a function with 4 arguments.
*
* @param argument 1 of the function
* @param argument 2 of the function
* @param argument 3 of the function
* @param argument 4 of the function
* @param return type of the function
* @author Daniel Dietrich
* @since 1.1.0
*/
@FunctionalInterface
public interface CheckedFunction4 extends λ {
/**
* The serial version uid.
*/
long serialVersionUID = 1L;
/**
* Creates a {@code CheckedFunction4} based on
*
*
* Examples (w.l.o.g. referring to Function1):
* // using a lambda expression
* Function1<Integer, Integer> add1 = Function1.of(i -> i + 1);
*
* // using a method reference (, e.g. Integer method(Integer i) { return i + 1; })
* Function1<Integer, Integer> add2 = Function1.of(this::method);
*
* // using a lambda reference
* Function1<Integer, Integer> add3 = Function1.of(add1::apply);
*
*
* Caution: Reflection loses type information of lambda references.
*
// type of a lambda expression
* Type<?, ?> type1 = add1.getType(); // (Integer) -> Integer
*
* // type of a method reference
* Type<?, ?> type2 = add2.getType(); // (Integer) -> Integer
*
* // type of a lambda reference
* Type<?, ?> type3 = add3.getType(); // (Object) -> Object
*
*
* @param methodReference (typically) a method reference, e.g. {@code Type::method}
* @param return type
* @param 1st argument
* @param 2nd argument
* @param 3rd argument
* @param 4th argument
* @return a {@code CheckedFunction4}
*/
static CheckedFunction4 of(CheckedFunction4 methodReference) {
return methodReference;
}
/**
* Lifts the given {@code partialFunction} into a total function that returns an {@code Option} result.
*
* @param partialFunction a function that is not defined for all values of the domain (e.g. by throwing)
* @param return type
* @param 1st argument
* @param 2nd argument
* @param 3rd argument
* @param 4th argument
* @return a function that applies arguments to the given {@code partialFunction} and returns {@code Some(result)}
* if the function is defined for the given arguments, and {@code None} otherwise.
*/
static Function4> lift(CheckedFunction4 partialFunction) {
return (t1, t2, t3, t4) -> Try.of(() -> partialFunction.apply(t1, t2, t3, t4)).getOption();
}
/**
* Applies this function to 4 arguments and returns the result.
*
* @param t1 argument 1
* @param t2 argument 2
* @param t3 argument 3
* @param t4 argument 4
* @return the result of function application
* @throws Throwable if something goes wrong applying this function to the given arguments
*/
R apply(T1 t1, T2 t2, T3 t3, T4 t4) throws Throwable;
/**
* Applies this function partially to one argument.
*
* @param t1 argument 1
* @return a partial application of this function
* @throws Throwable if something goes wrong partially applying this function to the given arguments
*/
default CheckedFunction3 apply(T1 t1) throws Throwable {
return (T2 t2, T3 t3, T4 t4) -> apply(t1, t2, t3, t4);
}
/**
* Applies this function partially to two arguments.
*
* @param t1 argument 1
* @param t2 argument 2
* @return a partial application of this function
* @throws Throwable if something goes wrong partially applying this function to the given arguments
*/
default CheckedFunction2 apply(T1 t1, T2 t2) throws Throwable {
return (T3 t3, T4 t4) -> apply(t1, t2, t3, t4);
}
/**
* Applies this function partially to three arguments.
*
* @param t1 argument 1
* @param t2 argument 2
* @param t3 argument 3
* @return a partial application of this function
* @throws Throwable if something goes wrong partially applying this function to the given arguments
*/
default CheckedFunction1 apply(T1 t1, T2 t2, T3 t3) throws Throwable {
return (T4 t4) -> apply(t1, t2, t3, t4);
}
@Override
default int arity() {
return 4;
}
@Override
default CheckedFunction1>>> curried() {
return t1 -> t2 -> t3 -> t4 -> apply(t1, t2, t3, t4);
}
@Override
default CheckedFunction1, R> tupled() {
return t -> apply(t._1, t._2, t._3, t._4);
}
@Override
default CheckedFunction4 reversed() {
return (t4, t3, t2, t1) -> apply(t1, t2, t3, t4);
}
@Override
default CheckedFunction4 memoized() {
if (isMemoized()) {
return this;
} else {
final Object lock = new Object();
final Map, R> cache = new HashMap<>();
final CheckedFunction1, R> tupled = tupled();
return (CheckedFunction4 & Memoized) (t1, t2, t3, t4) -> {
final R result;
synchronized (lock) {
result = cache.computeIfAbsent(Tuple.of(t1, t2, t3, t4), t -> Try.of(() -> tupled.apply(t)).get());
}
return result;
};
}
}
/**
* Returns a composed function that first applies this CheckedFunction4 to the given argument and then applies
* {@linkplain CheckedFunction1} {@code after} to the result.
*
* @param return type of after
* @param after the function applied after this
* @return a function composed of this and after
* @throws NullPointerException if after is null
*/
default CheckedFunction4 andThen(CheckedFunction1 super R, ? extends V> after) {
Objects.requireNonNull(after, "after is null");
return (t1, t2, t3, t4) -> after.apply(apply(t1, t2, t3, t4));
}
}