javaslang.CheckedFunction3 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javaslang Show documentation
Show all versions of javaslang Show documentation
Javaslang is a Java standard library extension built for Java 8 and above.
/* / \____ _ _ ____ ______ / \ ____ __ _______
* / / \/ \ / \/ \ / /\__\/ // \/ \ // /\__\ 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 three arguments.
*
* @param argument 1 of the function
* @param argument 2 of the function
* @param argument 3 of the function
* @param return type of the function
* @author Daniel Dietrich
* @since 1.1.0
*/
@FunctionalInterface
public interface CheckedFunction3 extends λ {
/**
* The serial version uid.
*/
long serialVersionUID = 1L;
/**
* Creates a {@code CheckedFunction3} 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
* @return a {@code CheckedFunction3}
*/
static CheckedFunction3 of(CheckedFunction3 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
* @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 Function3> lift(CheckedFunction3 partialFunction) {
return (t1, t2, t3) -> Try.of(() -> partialFunction.apply(t1, t2, t3)).getOption();
}
/**
* Applies this function to three arguments and returns the result.
*
* @param t1 argument 1
* @param t2 argument 2
* @param t3 argument 3
* @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) 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 CheckedFunction2 apply(T1 t1) throws Throwable {
return (T2 t2, T3 t3) -> apply(t1, t2, t3);
}
/**
* 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 CheckedFunction1 apply(T1 t1, T2 t2) throws Throwable {
return (T3 t3) -> apply(t1, t2, t3);
}
@Override
default int arity() {
return 3;
}
@Override
default CheckedFunction1>> curried() {
return t1 -> t2 -> t3 -> apply(t1, t2, t3);
}
@Override
default CheckedFunction1, R> tupled() {
return t -> apply(t._1, t._2, t._3);
}
@Override
default CheckedFunction3 reversed() {
return (t3, t2, t1) -> apply(t1, t2, t3);
}
@Override
default CheckedFunction3 memoized() {
if (isMemoized()) {
return this;
} else {
final Object lock = new Object();
final Map, R> cache = new HashMap<>();
final CheckedFunction1, R> tupled = tupled();
return (CheckedFunction3 & Memoized) (t1, t2, t3) -> {
final R result;
synchronized (lock) {
result = cache.computeIfAbsent(Tuple.of(t1, t2, t3), t -> Try.of(() -> tupled.apply(t)).get());
}
return result;
};
}
}
/**
* Returns a composed function that first applies this CheckedFunction3 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 CheckedFunction3 andThen(CheckedFunction1 super R, ? extends V> after) {
Objects.requireNonNull(after, "after is null");
return (t1, t2, t3) -> after.apply(apply(t1, t2, t3));
}
}