io.vavr.CheckedFunction2 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vavr Show documentation
Show all versions of vavr Show documentation
Vavr is an object-functional library for Java 8+
/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr;
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\
G E N E R A T O R C R A F T E D
\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
import static io.vavr.CheckedFunction2Module.sneakyThrow;
import io.vavr.control.Option;
import io.vavr.control.Try;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Represents a function with two arguments.
*
* @param argument 1 of the function
* @param argument 2 of the function
* @param return type of the function
* @author Daniel Dietrich
*/
@FunctionalInterface
public interface CheckedFunction2 extends Lambda {
/**
* The serial version uid.
*/
long serialVersionUID = 1L;
/**
* Creates a {@code CheckedFunction2} 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
* @return a {@code CheckedFunction2}
*/
static CheckedFunction2 of(CheckedFunction2 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
* @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.
*/
@SuppressWarnings("RedundantTypeArguments")
static Function2> lift(CheckedFunction2 super T1, ? super T2, ? extends R> partialFunction) {
return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2)).toOption();
}
/**
* Lifts the given {@code partialFunction} into a total function that returns an {@code Try} 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
* @return a function that applies arguments to the given {@code partialFunction} and returns {@code Success(result)}
* if the function is defined for the given arguments, and {@code Failure(throwable)} otherwise.
*/
static Function2> liftTry(CheckedFunction2 super T1, ? super T2, ? extends R> partialFunction) {
return (t1, t2) -> Try.of(() -> partialFunction.apply(t1, t2));
}
/**
* Narrows the given {@code CheckedFunction2 super T1, ? super T2, ? extends R>} to {@code CheckedFunction2}
*
* @param f A {@code CheckedFunction2}
* @param return type
* @param 1st argument
* @param 2nd argument
* @return the given {@code f} instance as narrowed type {@code CheckedFunction2}
*/
@SuppressWarnings("unchecked")
static CheckedFunction2 narrow(CheckedFunction2 super T1, ? super T2, ? extends R> f) {
return (CheckedFunction2) f;
}
/**
* Applies this function to two arguments and returns the result.
*
* @param t1 argument 1
* @param t2 argument 2
* @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) throws Throwable;
/**
* Applies this function partially to one argument.
*
* @param t1 argument 1
* @return a partial application of this function
*/
default CheckedFunction1 apply(T1 t1) {
return (T2 t2) -> apply(t1, t2);
}
@Override
default int arity() {
return 2;
}
/**
* Returns a function that always returns the constant
* value that you give in parameter.
*
* @param generic parameter type 1 of the resulting function
* @param generic parameter type 2 of the resulting function
* @param the result type
* @param value the value to be returned
* @return a function always returning the given value
*/
static CheckedFunction2 constant(R value) {
return (t1, t2) -> value;
}
@Override
default Function1> curried() {
return t1 -> t2 -> apply(t1, t2);
}
@Override
default CheckedFunction1, R> tupled() {
return t -> apply(t._1, t._2);
}
@Override
default CheckedFunction2 reversed() {
return (t2, t1) -> apply(t1, t2);
}
@Override
default CheckedFunction2 memoized() {
if (isMemoized()) {
return this;
} else {
final Map, R> cache = new HashMap<>();
return (CheckedFunction2 & Memoized) (t1, t2)
-> Memoized.of(cache, Tuple.of(t1, t2), t -> Try.of(() -> apply(t1, t2)).get());
}
}
/**
* Return a composed function that first applies this CheckedFunction2 to the given arguments and in case of throwable
* try to get value from {@code recover} function with same arguments and throwable information.
*
* @param recover the function applied in case of throwable
* @return a function composed of this and recover
* @throws NullPointerException if recover is null
*/
default Function2 recover(Function super Throwable, ? extends BiFunction super T1, ? super T2, ? extends R>> recover) {
Objects.requireNonNull(recover, "recover is null");
return (t1, t2) -> {
try {
return this.apply(t1, t2);
} catch (Throwable throwable) {
final BiFunction super T1, ? super T2, ? extends R> func = recover.apply(throwable);
Objects.requireNonNull(func, () -> "recover return null for " + throwable.getClass() + ": " + throwable.getMessage());
return func.apply(t1, t2);
}
};
}
/**
* Returns an unchecked function that will sneaky throw if an exceptions occurs when applying the function.
*
* @return a new Function2 that throws a {@code Throwable}.
*/
default Function2 unchecked() {
return (t1, t2) -> {
try {
return apply(t1, t2);
} catch(Throwable t) {
return sneakyThrow(t);
}
};
}
/**
* Returns a composed function that first applies this CheckedFunction2 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 CheckedFunction2 andThen(CheckedFunction1 super R, ? extends V> after) {
Objects.requireNonNull(after, "after is null");
return (t1, t2) -> after.apply(apply(t1, t2));
}
}
interface CheckedFunction2Module {
// DEV-NOTE: we do not plan to expose this as public API
@SuppressWarnings("unchecked")
static R sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}