All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.simplaex.bedrock.Functions Maven / Gradle / Ivy

There is a newer version: 2020.02.27
Show newest version
package com.simplaex.bedrock;

import lombok.experimental.UtilityClass;

import javax.annotation.Nonnull;
import java.util.Objects;
import java.util.function.*;

@UtilityClass
public class Functions {

  /**
   * Returns the identity function. Identical to {@link Function#identity()}.
   *
   * @param  The type of the argument and return value.
   * @return A function that always returns what is passed into it.
   */
  @Nonnull
  public static  UnaryOperator id() {
    return x -> x;
  }

  /**
   * Returns a function that ignores it's arguments and always returns the
   * given value.
   *
   * @param a   The given value.
   * @param  The type of the argument which is returned by the returned function.
   * @param  The type of the returned functions parameter.
   * @return The constant function.
   */
  @Nonnull
  public static  Function constant(final A a) {
    return ignored -> a;
  }

  @Nonnull
  public static  ToIntFunction constantInt(final int a) {
    return ignored -> a;
  }

  @Nonnull
  public static  ToLongFunction constantLong(final long a) {
    return ignored -> a;
  }

  @Nonnull
  public static  ToDoubleFunction constantDouble(final double a) {
    return ignored -> a;
  }

  @Nonnull
  public static  IntFunction intConstant(final A a) {
    return ignored -> a;
  }

  @Nonnull
  public static  LongFunction longConstant(final A a) {
    return ignored -> a;
  }

  @Nonnull
  public static  DoubleFunction doubleConstant(final A a) {
    return ignored -> a;
  }

  @Nonnull
  public static  Function> constant() {
    return a -> b -> a;
  }

  @Nonnull
  public static  Function compose(@Nonnull final Function f, @Nonnull final Function g) {
    return a -> f.apply(g.apply(a));
  }

  @Nonnull
  public static  Function> curry(@Nonnull final BiFunction f) {
    return a -> b -> f.apply(a, b);
  }

  @Nonnull
  public static  Function, C> curryPair(@Nonnull final BiFunction f) {
    return p -> f.apply(p.fst(), p.snd());
  }

  @Nonnull
  public static  Function> curry(@Nonnull final Function, C> f) {
    return a -> b -> f.apply(Pair.of(a, b));
  }

  @Nonnull
  public static  BiFunction uncurry(@Nonnull final Function> f) {
    return (a, b) -> f.apply(a).apply(b);
  }

  @Nonnull
  public static  Function, C> uncurryPair(@Nonnull final Function> f) {
    return p -> f.apply(p.fst()).apply(p.snd());
  }

  @Nonnull
  public static  Predicate not(@Nonnull final Predicate predicate) {
    Objects.requireNonNull(predicate, "'predicate' must not be null");
    return predicate.negate();
  }

  /**
   * Combines many predicates into a predicate that accepts its input only if it passes all predicates.
   *
   * @param ps  The predicates - if no predicates are given the predicate will return true always.
   * @param  The type of the value to be tested by the predicates.
   * @return
   */
  @SuppressWarnings("unchecked")
  @SafeVarargs
  @Nonnull
  public static  Predicate and(final Predicate... ps) {
    return c -> {
      for (final Predicate p : ps) {
        if (!((Predicate) p).test(c)) {
          return false;
        }
      }
      return true;
    };
  }

  /**
   * Combines many predicates into a predicate that accepts its input it if it passes one of these.
   *
   * @param ps  The predicates - if no predicates are given the predicate will return false always.
   * @param  The type of the value to be tested by the predicates.
   * @return
   */
  @SuppressWarnings("unchecked")
  @SafeVarargs
  @Nonnull
  public static  Predicate or(final Predicate... ps) {
    return c -> {
      for (final Predicate p : ps) {
        if (((Predicate) p).test(c)) {
          return true;
        }
      }
      return false;
    };
  }

  /**
   * Turns a function that results in a boxed Boolean into a Predicate.
   *
   * @param predicate The function.
   * @param        The type of the argument of the function.
   * @return The same function as a Predicate.
   */
  @Nonnull
  public static  Predicate predicate(@Nonnull final Function predicate) {
    return predicate::apply;
  }

  @Nonnull
  public static  Function bind(@Nonnull final BiFunction f, final A a) {
    return b -> f.apply(a, b);
  }

  @FunctionalInterface
  public interface ToBooleanBiFunction {
    boolean applyAsBool(final A a, final B b);
  }

  @Nonnull
  public static  Predicate bindToBool(@Nonnull final ToBooleanBiFunction f, final A a) {
    return b -> f.applyAsBool(a, b);
  }

  @Nonnull
  public static LongUnaryOperator bindLong(@Nonnull final LongBinaryOperator f, final long a) {
    return b -> f.applyAsLong(a, b);
  }

  @Nonnull
  public static DoubleUnaryOperator bindDouble(@Nonnull final DoubleBinaryOperator f, final double a) {
    return b -> f.applyAsDouble(a, b);
  }

  @Nonnull
  public static  Function2 flip(@Nonnull final BiFunction f) {
    return (a, b) -> f.apply(b, a);
  }

  public static  Function1 f1(final Function f) {
    return f::apply;
  }

  public static  Function2 f2(final BiFunction f) {
    return f::apply;
  }

  public static  void call(final T arg, final Consumer consumer) {
    consumer.accept(arg);
  }

  public static  void call(final T t, final U u, final BiConsumer consumer) {
    consumer.accept(t, u);
  }

  public static  R apply(final A arg, final Function f) {
    return f.apply(arg);
  }

  public static  R apply(final A arg1, final B arg2, final BiFunction f) {
    return f.apply(arg1, arg2);
  }

}