javaslang.Function1 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 java.util.function.Function;
import javaslang.control.Option;
import javaslang.control.Try;
/**
* Represents a function with one argument.
*
* @param argument 1 of the function
* @param return type of the function
* @author Daniel Dietrich
* @since 1.1.0
*/
@FunctionalInterface
public interface Function1 extends λ, Function {
/**
* The serial version uid.
*/
long serialVersionUID = 1L;
/**
* Creates a {@code Function1} 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
* @return a {@code Function1}
*/
static Function1 of(Function1 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
* @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 Function1> lift(Function1 partialFunction) {
return (t1) -> Try.of(() -> partialFunction.apply(t1)).getOption();
}
/**
* Returns the identity Function1, i.e. the function that returns its input.
*
* @param argument type (and return type) of the identity function
* @return the identity Function1
*/
static Function1 identity() {
return t -> t;
}
/**
* Applies this function to one argument and returns the result.
*
* @param t1 argument 1
* @return the result of function application
*
*/
R apply(T1 t1);
@Override
default int arity() {
return 1;
}
@Override
default Function1 curried() {
return this;
}
@Override
default Function1, R> tupled() {
return t -> apply(t._1);
}
@Override
default Function1 reversed() {
return this;
}
@Override
default Function1 memoized() {
if (isMemoized()) {
return this;
} else {
final Lazy forNull = Lazy.of(() -> apply(null));
final Object lock = new Object();
final Map cache = new HashMap<>();
return (Function1 & Memoized) t1 -> {
if (t1 == null) {
return forNull.get();
} else {
final R result;
synchronized (lock) {
result = cache.computeIfAbsent(t1, this::apply);
}
return result;
}
};
}
}
/**
* Returns a composed function that first applies this Function1 to the given argument and then applies
* {@linkplain Function} {@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 Function1 andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after, "after is null");
return (t1) -> after.apply(apply(t1));
}
/**
* Returns a composed function that first applies the {@linkplain Function} {@code before} the
* given argument and then applies this Function1 to the result.
*
* @param argument type of before
* @param before the function applied before this
* @return a function composed of before and this
* @throws NullPointerException if before is null
*/
default Function1 compose(Function super V, ? extends T1> before) {
Objects.requireNonNull(before, "before is null");
return v -> apply(before.apply(v));
}
}