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

net.sf.staccatocommons.lang.tuple.Tuples Maven / Gradle / Ivy

/*
 Copyright (c) 2011, The Staccato-Commons Team

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; version 3 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.
 */
package net.sf.staccatocommons.lang.tuple;

import net.sf.staccatocommons.defs.Applicable;
import net.sf.staccatocommons.defs.function.Function;
import net.sf.staccatocommons.defs.function.Function2;
import net.sf.staccatocommons.defs.function.Function3;
import net.sf.staccatocommons.defs.partial.FirstAware;
import net.sf.staccatocommons.defs.partial.FourthAware;
import net.sf.staccatocommons.defs.partial.SecondAware;
import net.sf.staccatocommons.defs.partial.ThirdAware;
import net.sf.staccatocommons.defs.predicate.Predicate;
import net.sf.staccatocommons.defs.predicate.Predicate2;
import net.sf.staccatocommons.defs.tuple.Tuple2;
import net.sf.staccatocommons.defs.tuple.Tuple3;
import net.sf.staccatocommons.defs.tuple.Tuple4;
import net.sf.staccatocommons.lang.function.AbstractFunction;
import net.sf.staccatocommons.lang.function.AbstractFunction2;
import net.sf.staccatocommons.lang.function.AbstractFunction3;
import net.sf.staccatocommons.lang.function.Functions;
import net.sf.staccatocommons.lang.predicate.AbstractPredicate2;
import net.sf.staccatocommons.restrictions.Constant;
import net.sf.staccatocommons.restrictions.check.NonNull;

/**
 * Class methods hub for creating {@link AbstractTuple}s, and obtaining
 * Tuple-related functions
 * 
 * @author flbulgarelli
 * 
 */
public class Tuples {

  /**
   * Answers a function that returns the first component of a tuple
   * 
   * @param 
   *          type of the first element
   * @return a constant function
   */
  @Constant
  public static  Function, A> first() {
    return new AbstractFunction, A>() {
      public A apply(FirstAware arg) {
        return arg._0();
      }
    };
  }

  /**
   * Answers a function that returns the second component of a tuple
   * 
   * @param 
   *          type of the second element
   * @return a constant function
   */
  @Constant
  public static  Function, A> second() {
    return new AbstractFunction, A>() {
      public A apply(SecondAware arg) {
        return arg._1();
      }
    };
  }

  /**
   * Answers a function that returns the third component of a tuple
   * 
   * @param 
   *          type of the third element
   * @return a constant function
   */
  @Constant
  public static  Function, A> third() {
    return new AbstractFunction, A>() {
      public A apply(ThirdAware arg) {
        return arg._2();
      }
    };
  }

  /**
   * Answers a function that returns the fourth component of a tuple
   * 
   * @param 
   *          type of the fourth element
   * @return a constant function
   */
  @Constant
  public static  Function, A> fourth() {
    return new AbstractFunction, A>() {
      public A apply(FourthAware arg) {
        return arg._3();
      }
    };
  }

  /**
   * Creates a new {@link Quadruple}
   * 
   * @param 
   * @param 
   * @param 
   * @param 
   * @param first
   * @param second
   * @param third
   * @param fourth
   * @return a new {@link Quadruple}. Non null.
   */
  @NonNull
  public static  Tuple4 _(T1 first, T2 second, T3 third, T4 fourth) {
    return new Quadruple(first, second, third, fourth);
  }

  /**
   * Creates a new {@link Tuple3}
   * 
   * @param 
   * @param 
   * @param 
   * @param first
   * @param second
   * @param third
   * @return a new {@link Tuple3}. Non null.
   */
  @NonNull
  public static  Tuple3 _(T1 first, T2 second, T3 third) {
    return new Triple(first, second, third);
  }

  /**
   * Creates a new {@link Tuple2}
   * 
   * @param 
   * @param 
   * @param first
   * @param second
   * @return a new {@link Tuple2}. Non null.
   */
  @NonNull
  public static  Tuple2 _(T1 first, T2 second) {
    return new Pair(first, second);
  }

  /**
   * Answers a function that creates {@link Tuple3}s for its arguments
   * 
   * @param 
   * @param 
   * @return a new {@link Function3}
   */
  @Constant
  public static  Function3> toTuple3() {
    return new AbstractFunction3>() {
      public Tuple3 apply(T1 arg0, T2 arg1, T3 arg2) {
        return _(arg0, arg1, arg2);
      }
    };
  }

  /**
   * Answers a function that creates {@link Tuple2}s for its arguments
   * 
   * @param 
   * @param 
   * @param 
   * @return a new {@link Function2}
   */
  @Constant
  public static  Function2> toTuple2() {
    return new AbstractFunction2>() {
      public Tuple2 apply(T1 arg0, T2 arg1) {
        return _(arg0, arg1);
      }
    };
  }

  /**
   * Curries the given
   * {@code function} that takes a single {@link Tuple2}, by returning a new one
   * that takes two arguments, one for each component of the pair
   * 
   * @param 
   * @param 
   * @param 
   * @param function
   *          the function to curry
   * @return a new {@link Function2}
   */
  public static  Function2 curry(final Function, C> function) {
    return new AbstractFunction2() {
      public C apply(A arg0, B arg1) {
        return function.apply(_(arg0, arg1));
      }
    };
  }

  /**
   * Curries the given
   * {@code function} that takes a single {@link Tuple3}, by returning a new one
   * that takes three arguments, one for each component of the triple
   * 
   * @param 
   * @param 
   * @param 
   * @param function
   *          the function to curry
   * @return a new {@link Function3}
   */
  public static  Function3 curry3(final Function, D> function) {
    return new AbstractFunction3() {
      public D apply(A arg0, B arg1, C arg2) {
        return function.apply(_(arg0, arg1, arg2));
      }
    };
  }

  /**
   * Curries the given
   * {@code predicate} that takes a single {@link Tuple2}, by returning a new
   * one that takes two arguments, one for each component of the pair
   * 
   * @param 
   * @param 
   * @param 
   * @param predicate
   *          the function to curry
   * @return a new {@link Predicate2}
   */
  public static  Predicate2 curry(final Predicate> predicate) {
    return new AbstractPredicate2() {
      public boolean eval(A arg0, B arg1) {
        return predicate.eval(_(arg0, arg1));
      };
    };
  }

  /*
   * Loosely based on
   * http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Arrow.html
   */

  /**
   * Combines two functions into one that takes a pair and applies the first function to the first component, and the second
   * function to the second component, and returns the pair of results. 
   * 
   * Functions get combined as in the following figure:
   * 
 
   * >------function0----->
   * 
   * >------function1----->
   * 
* Example: * *
   * zip(NumberTypes.add(10), NumberTypes.add(1)).apply(_(2,0))
   * 
* * Returns the tuple * *
   * (12, 1)
   * 
* * @param function0 * @param function1 * @return a new function that zips both given functions */ public static Function, Tuple2> zip( final Applicable function0, final Applicable function1) { return new AbstractFunction, Tuple2>() { public Tuple2 apply(Tuple2 arg) { return _((C) function0.apply(arg._0()), (D) function1.apply(arg._1())); } }; } public static Function, C> merge(final Applicable function) { return new AbstractFunction, C>() { public C apply(Tuple2 arg) { return function.apply(arg._1()); } }; } /** * Answers a function that applies both given functions to its argument, and * returns both results, as a {@link Pair}. * * Functions get combined as in the following figure: * *
   *      +------function0----->
   * >----+
   *      +------function1----->
   * 
* Example: * *
   * branch(NumberTypes.add(10), Compare.greaterThan(5)).apply(2)
   * 
* * Returns the tuple * *
   * (12, false)
   * 
* * * @param
* @param * @param * @param function0 * the function whose result will be the first component of the tuple * @param function1 * the function whose result will be the second component of the * tuple * @return a new {@link Function} that "branches" its argument */ public static Function> branch(final Applicable function0, final Applicable function1) { return new AbstractFunction>() { public Tuple2 apply(A arg) { return _((B) function0.apply(arg), (C) function1.apply(arg)); } }; } /** * Answers a function that returns a Tuple2 that contains the original * function argument and the result of applying * *
   *      +------function0----->
   * >----+
   *      +-------------------->
   * 
* * @param
* @param * @param function0 * @return a new {@link Function} */ public static Function> clone(final Applicable function0) { return branch(Functions. identity(), function0); } }