![JAR search and dependency download from the Maven repository](/logo.png)
io.atlassian.fugue.Functions Maven / Gradle / Ivy
/*
Copyright 2011 Atlassian
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package io.atlassian.fugue;
import java.io.Serializable;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static io.atlassian.fugue.Option.option;
import static io.atlassian.fugue.Unit.Unit;
import static java.util.Objects.requireNonNull;
/**
* Utility methods for Functions
*
* Note that this class defines Partial Functions to be functions that return an
* {@link io.atlassian.fugue.Option} of the result type, and has some methods
* for creating them.
*
* @since 1.1
*/
public class Functions {
// /CLOVER:OFF
private Functions() {}
// /CLOVER:ON
/**
* Returns the composition of two functions. For {@code f: A->B} and
* {@code g: B->C}, composition is defined as the function h such that
* {@code h(a) == g(f(a))} for each {@code a}.
*
* @param The start type
* @param The intermediate type
* @param The finished type
* @param g the second function to apply, must not be null
* @param f the first function to apply, must not be null
* @return the composition of {@code f} and {@code g}
* @see function
* composition
*/
public static Function compose(final Function super B, ? extends C> g, final Function super A, ? extends B> f) {
return new FunctionComposition<>(g, f);
}
private static class FunctionComposition implements Function, Serializable {
private final Function super B, ? extends C> g;
private final Function super A, ? extends B> f;
FunctionComposition(final Function super B, ? extends C> g, final Function super A, ? extends B> f) {
this.g = requireNonNull(g);
this.f = requireNonNull(f);
}
@Override public C apply(final A a) {
return g.apply(f.apply(a));
}
@Override public boolean equals(final Object obj) {
if (obj instanceof FunctionComposition) {
final FunctionComposition, ?, ?> that = (FunctionComposition, ?, ?>) obj;
return f.equals(that.f) && g.equals(that.g);
}
return false;
}
@Override public int hashCode() {
return f.hashCode() ^ g.hashCode();
}
@Override public String toString() {
return g.toString() + "(" + f.toString() + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Performs function application within a higher-order function (applicative
* functor pattern).
*
* @param ca A function to apply within a higher-order function.
* @param cab The higher-order function to apply a function to.
* @return A new function after applying the given higher-order function to
* the given function.
* @since 4.0
*/
public static Function ap(final Function ca, final Function> cab) {
return m -> ca.andThen(cab.apply(m)).apply(m);
}
/**
* Apply f to each element in elements, with each application using the result
* of the previous application as the other argument to f. zero is used as the
* first 'result' value. The final result is returned.
*
* @param the element type
* @param the final result type
* @param f the function to apply to all the elements
* @param zero the starting point for the function
* @param elements the series of which each element will be accumulated into a
* result
* @return the result of accumulating the application of f to all elements
* @since 1.1
*/
public static T fold(final BiFunction super T, F, T> f, final T zero, final Iterable extends F> elements) {
T currentValue = zero;
for (final F element : elements) {
currentValue = f.apply(currentValue, element);
}
return currentValue;
}
/**
* Apply f to each element in elements, with each application using the result
* of the previous application as the other argument to f. zero is used as the
* first 'result' value. The final result is returned.
*
* @param the element type
* @param the accumulator function input type
* @param the return result type
* @param f the function to apply to all elements
* @param zero the starting point for the function
* @param elements the series of which each element will be accumulated into a
* result
* @return the result of accumulating the application of f to all elements
* @since 1.1
*/
public static T fold(final Function, T> f, final T zero, final Iterable extends F> elements) {
return fold(toBiFunction(f), zero, elements);
}
/**
* Function that takes another function and applies it to the argument.
*
* @param the argument and function input type
* @param the result type
* @param arg the argument that will be applied to any input functions
* @return a function that takes a function from A to B , applies the arg and
* returns the result
* @since 1.1
*/
public static Function, B> apply(final A arg) {
return new Function, B>() {
@Override public B apply(final Function f) {
return f.apply(arg);
}
@Override public String toString() {
return "Apply";
}
};
}
/**
* Function that takes another function and applies it to the argument
* supplied by the parameter.
*
* @param lazyA the supplier of the argument that will be applied to any input
* functions
* @param the type of the argument supplied, and the function input type
* @param the result type of the function
* @return a function that takes a function from A to B, applies the argument
* from the supplier and returns the result
* @since 2.0
*/
public static Function, B> apply(final Supplier lazyA) {
return new Function, B>() {
@Override public B apply(final Function f) {
return f.apply(lazyA.get());
}
@Override public String toString() {
return "ApplySupplier";
}
};
}
/**
* Partial Function that does a type check and matches if the value is of the
* right type.
*
* @param the input type
* @param the type we expect it to be
* @param cls the type to check against, must not be null
* @return a function that returns a Some with the value if of the right type
* otherwise a None
* @since 1.2
*/
public static Function> isInstanceOf(final Class cls) {
return new InstanceOf<>(cls);
}
static class InstanceOf implements Function> {
private final Class cls;
InstanceOf(final Class cls) {
this.cls = requireNonNull(cls);
}
@Override public Option apply(final A a) {
return (cls.isAssignableFrom(a.getClass())) ? Option.some(cls.cast(a)) : Option. none();
}
@Override public String toString() {
return "InstanceOf";
}
@Override public int hashCode() {
return cls.hashCode();
}
static final long serialVersionUID = 0;
}
/**
* Create a PartialFunction from a {@link java.util.function.Predicate} and a
* {@link java.util.function.Function}.
*
* @param the input type
* @param the output type
* @param p the predicate to test the value against, must not be null
* @param f the function to apply if the predicate passes, must not be null
* @return a PartialFunction that tests the supplied predicate before applying
* the function.
* @since 1.2
*/
public static Function> partial(final Predicate super A> p, final Function super A, ? extends B> f) {
return new Partial<>(p, f);
}
static class Partial implements Function> {
private final Predicate super A> p;
private final Function super A, ? extends B> f;
Partial(final Predicate super A> p, final Function super A, ? extends B> f) {
this.p = requireNonNull(p);
this.f = requireNonNull(f);
}
@Override public Option apply(final A a) {
return (p.test(a)) ? option(f.apply(a)) : Option. none();
}
@Override public String toString() {
return "Partial";
}
@Override public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
}
/**
* Compose two PartialFunctions into one.
*
* Kleisli composition. In Haskell it is defined as >=>
,
* AKA
* "compose, fishy, compose"
*
* @param the input type
* @param the middle type
* @param the output type
* @param bc partial function from {@code B -> C}, must not be null
* @param ab partial function from {@code A -> B}, must not be null
* @return a PartialFunction that flatMaps g on to the result of applying f.
* @since 1.2
*/
public static Function> composeOption(final Function super B, ? extends Option extends C>> bc,
final Function super A, ? extends Option extends B>> ab) {
return new PartialComposer<>(ab, bc);
}
static class PartialComposer implements Function> {
private final Function super A, ? extends Option extends B>> ab;
private final Function super B, ? extends Option extends C>> bc;
PartialComposer(final Function super A, ? extends Option extends B>> ab, final Function super B, ? extends Option extends C>> bc) {
this.ab = requireNonNull(ab);
this.bc = requireNonNull(bc);
}
@Override public Option apply(final A a) {
return ab.apply(a).flatMap(bc);
}
@Override public String toString() {
return "PartialComposer";
}
@Override public int hashCode() {
return bc.hashCode() ^ ab.hashCode();
}
}
/**
* Converts a function that takes a pair of arguments to a function that takes
* two arguments
*
* @param the type of the left of the pair
* @param the type of the right of the pair
* @param the result type
* @param fpair the source function that takes a pair of arguments, must not
* be null
* @return a function that takes two arguments
* @since 2.0
*/
public static BiFunction toBiFunction(final Function, C> fpair) {
requireNonNull(fpair);
return new BiFunction() {
@Override public C apply(final A a, final B b) {
return fpair.apply(Pair.pair(a, b));
}
@Override public String toString() {
return "ToBiFunction";
}
};
}
/**
* Transforms a function that takes 2 arguments into a function that takes the
* first argument and return a new function that takes the second argument and
* return the final result.
*
* @param the type of the first argument
* @param the type of the second argument
* @param the type of the final result
* @param f2 the original function that takes 2 arguments, must not be null
* @return the curried form of the original function
* @since 2.0
*/
public static Function> curried(final BiFunction f2) {
requireNonNull(f2);
return new CurriedFunction<>(f2);
}
private static class CurriedFunction implements Function> {
private final BiFunction f2;
CurriedFunction(final BiFunction f2) {
this.f2 = f2;
}
@Override public Function apply(final A a) {
return b -> f2.apply(a, b);
}
@Override public String toString() {
return "CurriedFunction";
}
@Override public int hashCode() {
return f2.hashCode();
}
}
/**
* Transforms a function from {@code A -> (B -> C)} into a function from
* {@code B -> (A -> C)}.
*
* @param the type of the first argument
* @param the type of the second argument
* @param the type of the final result
* @param f2 the original function from {@code A -> (B -> C)}, must not be
* null
* @return the flipped form of the original function
* @since 2.0
*/
public static Function> flip(final Function> f2) {
requireNonNull(f2);
return new FlippedFunction<>(f2);
}
private static class FlippedFunction implements Function> {
private final Function> f2;
FlippedFunction(final Function> f2) {
this.f2 = f2;
}
@Override public Function apply(final B b) {
return a -> f2.apply(a).apply(b);
}
@Override public String toString() {
return "FlippedFunction";
}
@Override public int hashCode() {
return f2.hashCode();
}
}
/**
* Maps a function that returns nulls into a Partial function that returns an
* Option of the result.
*
* @param the input type
* @param the output type
* @param f the function that may return nulls
* @return a function that converts any nulls into Options
* @since 2.0
*/
public static Function> mapNullToOption(final Function super A, ? extends B> f) {
return Functions.compose(Functions. nullToOption(), f);
}
/**
* Function that turns null inputs into a none, and not-null inputs into some.
*
* @param the input type
* @return a function that never returns nulls.
* @since 2.2.1
*/
public static Function> nullToOption() {
return Options.toOption();
}
/**
* Takes a Function and memoizes (caches) the result for each input. This
* memoization is weak, so it shouldn't leak memory on its own, but equally it
* may expunge entries if no-one else is holding the reference in the
* meantime.
*
* NOTE: it is very important that the docs on the input type are read
* carefully. Failure to heed adhere to this will lead to unspecified behavior
* (bugs!)
*
* @param the input type, like any cache, this type should be a value,
* that is it should be immutable and have correct hashcode and equals
* implementations.
* @param the output type
* @param f the function who's output will be memoized, must not be null
* @return a function that memoizes the results of the function using the
* input as a weak key
* @since 2.2
*/
public static Function weakMemoize(final Function f) {
return WeakMemoizer.weakMemoizer(f);
}
/**
* Get a function that uses the Supplier as a factory for all inputs.
*
* @param the key type, ignored
* @param the result type
* @param supplier called for all inputs, must not be null
* @return the function
*
* @since 2.2
*/
static Function fromSupplier(final Supplier supplier) {
return new FromSupplier<>(supplier);
}
static class FromSupplier implements Function {
private final Supplier supplier;
FromSupplier(final Supplier supplier) {
this.supplier = requireNonNull(supplier, "supplier");
}
@Override public R apply(final D ignore) {
return supplier.get();
}
@Override public String toString() {
return "FromSupplier";
}
@Override public int hashCode() {
return supplier.hashCode();
}
}
/**
* Get a function (with {@link Unit} return type) that calls the consumer for
* all inputs.
*
* @param the key type
* @param consumer called for all inputs, must not be null
* @return the function
* @since 4.4.0
*/
public static Function fromConsumer(Consumer consumer) {
return new FromConsumer<>(consumer);
}
private static class FromConsumer implements Function {
private final Consumer consumer;
FromConsumer(final Consumer consumer) {
this.consumer = requireNonNull(consumer);
}
@Override public Unit apply(D d) {
consumer.accept(d);
return Unit();
}
@Override public String toString() {
return "FromConsumer";
}
@Override public int hashCode() {
return consumer.hashCode();
}
}
/**
* Returns the identity function. Consider using
* {@link java.util.function.Function#identity()}
*
* @return a {@link java.util.function.Function} that retruns it's input.
* @param a A object.
*/
@SuppressWarnings("unchecked") public static Function identity() {
// cast a singleton Function