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

jedi.functional.FunctionalPrimitives Maven / Gradle / Ivy

The newest version!
package jedi.functional;

import jedi.assertion.AssertionError;
import jedi.functors.ComposeableFunctor;
import jedi.functors.IdentityFunctor;
import jedi.option.None;
import jedi.option.Option;
import jedi.option.Options;
import jedi.option.Some;
import jedi.tuple.Tuple2;
import jedi.tuple.Tuples;

import java.util.*;

import static jedi.assertion.Assert.*;
import static jedi.functional.Coercions.*;
import static jedi.functional.Comparables.sort;
import static jedi.functional.Comparables.sortInPlace;
import static jedi.functional.FirstOrderLogic.invert;
import static jedi.functors.ComposeableFunctor.composeable;
import static jedi.option.Options.option;
import static jedi.option.Options.some;
import static jedi.tuple.Tuples.pair;

/**
 * I provide operations of the kind found in Functional Programming languages.
 * This allows you to remove a great deal of clutter from production code.
 * Ideally, you will never need to write another 'for' loop again, and a great
 * deal of explicit conditional logic should be removable as well.
 * 

* Generally, functions that transform collections (using functors or whatever) * preserve the iteration order of the given collection in the result. */ public class FunctionalPrimitives { private FunctionalPrimitives() { } private static final Comparator COLLECTION_SIZE_COMPARATOR = new Comparator() { public int compare(Collection o1, Collection o2) { return o1.size() - o2.size(); } }; private static void addToGroup(final K key, final V value, final Map> groups) { List group = groups.get(key); if (group == null) { groups.put(key, group = new ArrayList()); } group.add(value); } private static Collection toCollection(Iterable iterable) { return iterable instanceof Collection ? (Collection) iterable : asList(iterable); } private static List toList(Iterable iterable) { return iterable instanceof List ? (List) iterable : asList(iterable); } /** * Append all of the elements in all of the given collections * into one list. All of the elements of the first item in * collections are appended first, then the items in the second * collection, etc. * * @see #append(Iterable...) */ public static List append(final Iterable> iterables) { List result = new ArrayList(); for (Iterable iter : iterables) { addAll(result, iter); } return result; } /** * Append all of the elements in all of the given collections * into one list. All of the elements of the first item in * collections are appended first, then the items in the second * collection, etc. Equivalent to {@link #append(Iterable)} ({@link Coercions#list(Object...) list}(iterables)). * * @see #append(Iterable) * @see Coercions#list(Object...) */ public static List append(final Iterable... iterables) { return append(list(iterables)); } /** * Apply functor to each element of items and * return the list of results. * * @see #collect(Object[],Functor) */ public static List collect(final Iterable items, final Functor functor) { assertNotNull(items, "items must not be null"); assertNotNull(functor, "functor must not be null"); final List mapped = new ArrayList(); for (final T item : items) { mapped.add(functor.execute(item)); } return mapped; } /** * Apply functor to each element of items and * return the list of results. The iteration order of items is * preserved in the returned list. *

* Equivalent to collect(functor, asList(items)) * * @see #collect(Iterable, Functor) */ public static List collect(final T[] items, final Functor functor) { return collect(asList(items), functor); } /** * @see #collect(Iterable, Functor) */ public static List map(List list, Functor functor) { return collect(list, functor); } /** * @see #collect(Iterable, Functor) */ public static Set map(Set set, Functor functor) { return Coercions.asSet(collect(set, functor)); } /** * Get all but the first n elements of * items. See SRFI-1 */ public static List drop(final int n, final Iterable items) { assertNotNull(items, "items must not be null"); ArrayList list = new ArrayList(); int i = 0; for (T t : items) { if (i >= n) { list.add(t); } i++; } return list; } /** * Get all but the last n elements of items. See SRFI-1 */ public static List dropRight(final int n, final Iterable items) { assertNotNull(items, "items must not be null"); Collection collection = toCollection(items); assertLessThanOrEqualTo(collection.size(), n, "n should be less than or equal to items.size but is not"); return take(collection.size() - n, collection); } /** * Suppose there is a collection of items (c1, c2, c3), each of which * contains a collection i.e. (c1 = (c1_1, c1_2, ...), c2=(c2_1, * c2_2, ...). I can produce a collection containing all of the 'leaf' items * applied to functor * i.e.(c1_1, c1_2, ..., c2_1, c2_2) *

Synonymous with {@link #flatMap(Iterable, Functor)} *

Equivalent to {@link #append(Iterable) append}({@link #collect(Iterable, Functor) collect}(items, functor)) * * @param items * The collection of items containing the collection of leaves * @param functor * Given an element of the 'top' collection, this can obtain the * collection of 'leaf' objects to accumulate */ public static List flatten(final Iterable items, final Functor> functor) { return append(collect(items, functor)); } /** * Given a collection of items (c1, c2, c3), each of which * contains a collection i.e. (c1 = (c1_1, c1_2, ...), c2=(c2_1, * c2_2, ...). I produce a collection containing all of the 'leaf' items * i.e.(c1_1, c1_2, ..., c2_1, c2_2). *

Equivalent to {@link #flatten(Iterable, Functor)} and * {@link #flatMap(Iterable, Functor)} with the {@link IdentityFunctor}

* * @param items * The collection of items containing the collection of leaves */ public static List flatten(Iterable> items) { return flatten(items, IdentityFunctor.>identity()); } /** * Add all the elements of an iterable to a collection. */ public static Collection addAll(Collection list, Iterable iterable) { assertNotNull(list, "list must not be null"); assertNotNull(iterable, "iterable must not be null"); for (T object : iterable) { list.add(object); } return list; } /** * Fold passes each item of a collection with an accumulated value to a * functor. *

* For example, to sum the elements of a list: *

* *

	 *           Functor2<Integer, Integer, Integer> summer = new Functor2<Integer, Integer, Integer>() {
	 *           	public Integer execute(Integer accumulator, Integer value) {
	 *           		return accumulator + value;
	 *           	}
	 *           };
	 *           fold(10, summer, list(1, 2, 3, 4)) will return 20 (initial value of 10 + the sum of 1 .. 4)
	 * 
* *

* For a more comprehensive description, see SRFI-1 * @param initialValue the initial value for the fold * @param collection the collection over which to fold * @param functor2 the function to apply to values of the collection collected in Acc */ public static Acc fold(final InitialValue initialValue, final Iterable collection, final Functor2 functor2) { assertNotNull(collection, "collection must not be null"); assertNotNull(functor2, "functor2 must not be null"); Acc accumulated = initialValue; for (final T t : collection) { accumulated = functor2.execute(accumulated, t); } return accumulated; } /** * Reduce passes each item of a collection with an accumulated value to a functor yielding a single result. * The first value from the collection applied to the functor is used as the initial accumulator value. *

* For example, to sum the elements of a non-empty list: *

* *

	 *           Functor2<Integer, Integer, Integer> summer = new Functor2<Integer, Integer, Integer>() {
	 *           	public Integer execute(Integer accumulator, Integer value) {
	 *           		return accumulator + value;
	 *           	}
	 *           };
	 *           reduce(summer, list(1, 2, 3, 4)) will return 10
	 * 
* *

* For a more comprehensive description, see SRFI-1 * @param collection the collection over which to fold * @param functor2 the function to apply to values of the collection collected in Acc */ public static Acc reduce(final Iterable collection, final Functor2 functor2) { assertNotNull(collection, "collection must not be null"); assertNotNull(functor2, "functor2 must not be null"); assertTrue(hasItems(collection), "items must not be empty"); return fold(head(collection), tail(collection), functor2); } /** * Iterate over a collection of items applying the given * command to each */ public static Iterable forEach(final Iterable items, final Command command) { assertNotNull(command, "command must not be null"); assertNotNull(items, "items must not be null"); for (final T item : items) { command.execute(item); } return items; } /** * A synonym for {@link #partition(Iterable, Functor)} Group the elements of * a collection such that all elements that are mapped to the same value by * a given keyFunctor are in the same group. The groups are * returned as a map in which each value is a collection of values in one * group and whose key is the value returned by the keyFunctor * for all items in the group. */ public static Map> group(final Iterable toGroup, final Functor keyFunctor) { assertNotNull(keyFunctor, "keyFunctor must not be null"); assertNotNull(toGroup, "toGroup must not be null"); final Map> groups = new HashMap>(); for (final V v : toGroup) { addToGroup(keyFunctor.execute(v), v, groups); } return groups; } /** * A synonym for {@link #group(Iterable, Functor)} Partition the elements of * a collection such that all elements that are mapped to the same value by * a given keyFunctor are in the same partition. The groups are * returned as a map in which each value is a collection of values in one * partition and whose key is the value returned by the * keyFunctor for all items in the group. */ public static Map> partition(final Iterable toPartition, final Functor keyFunctor) { return group(toPartition, keyFunctor); } /** * Get the first item (in iteration order) from a collection. The collection * must contain at least one item or an * {@link jedi.assertion.AssertionError AssertionError} will be thrown. * * @return the first item in the collection * @throws jedi.assertion.AssertionError * if the collection is empty * @see #only(Collection) * @see #headOrNullIfEmpty(Iterable) * @see #headOrDefaultIfEmpty(Iterable, Object) */ public static T head(final Iterable items) { assertNotNull(items, "items must not be null"); assertTrue(hasItems(items), "items must not be empty"); return headOrNullIfEmpty(items); } /** * Get the first item (in iteration order) from a collection or * defaultValue (which may be null) if the collection is empty. * * @return the first item in the collection or defaultValue if * the collection is empty * @see #only(Collection) * @see #head(Iterable) * @see #headOrNullIfEmpty(Iterable) */ public static T headOrDefaultIfEmpty(final Iterable items, final T defaultValue) { assertNotNull(items, "items must not be null"); if (isEmpty(items)) { return defaultValue; } if (items instanceof List) { return ((List) items).get(0); } return items.iterator().next(); } /** * Get the first item (in iteration order) from a collection or * null if the collection is empty. * * @return the first item in the collection or null if the collection is * empty * @see #only(Collection) * @see #head(Iterable) * @see #headOrDefaultIfEmpty(Iterable, Object) */ public static T headOrNullIfEmpty(final Iterable items) { return headOrDefaultIfEmpty(items, null); } /** * Get the first item (in iteration order) from a collection as an * {@link Option}. * * @param items * @return the first item (in iteration order) from a collection as * {@link Some} or {@link None} if the collection is empty. */ public static Option headOption(final Iterable items) { return option(headOrNullIfEmpty(items)); } /** * Get the last item (in iteration order) from a collection. The collection * must contain at least one item or an * {@link jedi.assertion.AssertionError AssertionError} will be thrown. * * @return the last item in the collection * @throws jedi.assertion.AssertionError * if the collection is empty * @see #only(Collection) * @see #lastOrNullIfEmpty(Iterable) * @see #lastOrDefaultIfEmpty(Iterable, Object) */ public static T last(Iterable items) { assertNotNull(items, "items must not be null"); assertTrue(hasItems(items), "items must not be empty"); return lastOrNullIfEmpty(items); } /** * Get the last item (in iteration order) from a collection or * defaultValue (which may be null) if the collection is empty. * * @return the last item in the collection or defaultValue if * the collection is empty * @see #only(Collection) * @see #last(Iterable) * @see #lastOrNullIfEmpty(Iterable) */ public static T lastOrDefaultIfEmpty(Iterable items, T defaultValue) { assertNotNull(items, "items must not be null"); if (isEmpty(items)) { return defaultValue; } List l = toList(items); return l.get(l.size() - 1); } public static T lastOrNullIfEmpty(Iterable items) { return lastOrDefaultIfEmpty(items, null); } /** * Get the last item (in iteration order) from a collection as an * {@link Option}. * * @return the last item as a {@link Some} or {@link None} if the collection * is empty. */ public static Option lastOption(Collection items) { return option(lastOrNullIfEmpty(items)); } /** * An alias for head * * @see #head(Iterable) */ public static T first(Iterable collection) { return head(collection); } /** * Find the first item that matches the given filter * @return The first item that matches the given filter * @throws AssertionError if no match can be found */ public static T first(Iterable all, final Filter filter) { for (T t : all) { if(filter.execute(t)) { return t; } } throw new AssertionError("At least one item should match the filter"); } /** * Find the first item that matches the given filter or null if no match can be found * @return The first item that matches the given filter or null if no match can be found */ public static T firstOrDefault(Iterable all, final Filter filter, T defaultValue) { for (T t : all) { if(filter.execute(t)) { return t; } } return defaultValue; } /** * Find the first item that matches the given filter or null if no match can be found * @return The first item that matches the given filter or null if no match can be found */ public static T firstOrNull(Iterable all, final Filter filter) { return firstOrDefault(all, filter, null); } /** * Find the first item that matches the given filter * @return A Some Option on the first matching item or None if no items match */ public static Option firstOption(Iterable all, final Filter filter) { return Options.option(firstOrNull(all, filter)); } /** * Get the first item (in iteration order) from a collection as an * {@link Option}. * * @param items * @return the first item (in iteration order) from a collection as * {@link Some} or {@link None} if the collection is empty. */ public static Option firstOption(final Iterable items) { return option(headOrNullIfEmpty(items)); } /** * An alias for fold. * * @see #fold(Object, Iterable, Functor2) */ public static R inject(final I initialValue, final Iterable collection, final Functor2 functor2) { return fold(initialValue, collection, functor2); } /** * Join, with default delimiter (empty string) * * @see #join(Object[], String) */ public static String join(final Iterable items) { return join(items, ""); } public static String join(final Iterable items, final String delimiter) { assertNotNull(items, "items must not be null"); assertNotNull(delimiter, "delimiter must not be null"); Iterator iterator = items.iterator(); final StringBuffer sb = new StringBuffer(); while (iterator.hasNext()) { sb.append(iterator.next()); if (iterator.hasNext()) { sb.append(delimiter); } } return sb.toString(); } /** * Returns a string created by converting each element of an array to a * string, separated by delimiter. Emulates Array.join in Ruby. */ public static String join(final Object[] items, final String delimiter) { assertNotNull(items, "items must not be null"); return join(asList(items), delimiter); } /** * Returns an n-element list. Element i of the list, where 0 <= i < n, is * produced by the functor. For a more comprehensive description, see SRFI-1 * * @param n * the length of the list * @param functor * the functor taking an integer and returning an */ public static List listTabulate(final int n, final Functor functor) { assertNotNull(functor, "functor must not be null"); final List list = new ArrayList(n); for (int i = 0; i < n; i++) { list.add(functor.execute(i)); } return list; } /** * Find the biggest collection in a collection of collections * * @param collections * @return the shortest list */ public static > T longest(final Iterable collections) { assertNotNull(collections, "collections must not be null"); assertTrue(hasItems(collections), "collections must have at least one item"); return head(reverse(sortInPlace(asList(collections), COLLECTION_SIZE_COMPARATOR))); } /** * Returns an n-element list, whose elements are all the value * fill. For a more comprehensive description, see SRFI-1 */ public static List makeList(final int n, final T fill) { assertNotNull(fill, "fill must not be null"); final List list = new ArrayList(n); for (int i = 0; i < n; i++) { list.add(fill); } return list; } /** * Return the one and only item in the given collection. * * @return the item in the collection * @throws jedi.assertion.AssertionError * if the collection contains less or more than one item * @see #head(Iterable) * @see #headOrNullIfEmpty(Iterable) */ public static T only(final Collection items) { assertNotNull(items, "items must not be null"); assertEqual(1, items.size(), "items must contain only one element"); return head(items); } /** * Create the Cartesian product of two collections, using a {@link Functor2 * functor} as a factory of objects to represent the pair-wise products. */ public static List produce(final Iterable left, final Iterable right, final Functor2 factory) { final List product = new ArrayList(); for (final T t : left) { for (final U u : right) { product.add(factory.execute(t, u)); } } return product; } /** * Filter a collection of items, returning only those that do * not match a given filter, this is the inverse of select. * * @see #select(Iterable, Filter) */ public static List reject(final Iterable items, final Filter filter) { assertNotNull(filter, "filter must not be null"); assertNotNull(items, "items must not be null"); return select(items, invert(filter)); } public static List reverse(final Iterable items) { assertNotNull(items, "items must not be null"); List result = asList(items); Collections.reverse(result); return result; } /** * Filter a collection of items, returning only those that * match a given filter, this is the inverse of reject. * * @see #reject(Iterable, Filter) */ public static List select(final Iterable items, final Filter filter) { assertNotNull(filter, "filter must not be null"); assertNotNull(items, "items must not be null"); final List selected = new ArrayList(); for (final T item : items) { if (filter.execute(item)) { selected.add(item); } } return selected; } /** * Produce a single command that executes each of the given * commands in sequence */ public static Command sequence(final Command... commands) { return new Command() { public void execute(final T value) { for (final Command command : commands) { command.execute(value); } } }; } /** * Find the shortest list in a list of lists * * @param collections * @return the shortest list */ public static > T shortest(final Iterable collections) { assertNotNull(collections, "lists must not be null"); assertTrue(hasItems(collections), "lists must have at least one item"); return head(sort(asList(collections), COLLECTION_SIZE_COMPARATOR)); } public static boolean hasItems(final Iterable iterable) { return iterable.iterator().hasNext(); } public static boolean isEmpty(final Iterable iterable) { return !hasItems(iterable); } /** * Create a list from the nth elements of the given lists. */ public static List slice(final int n, final Iterable items) { assertNotNull(items, "lists must not be null"); assertGreaterThanOrEqualTo(0, n, "n must be greater than or equal to 0"); final List result = new ArrayList(); for (final List list : items) { result.add(list.get(n)); } return result; } /** * Create a list of string by splitting on a regex. * * @see java.lang.String#split(String) */ public static List split(final String item, final String regex) { assertNotNull(item, "item must not be null"); assertNotNull(regex, "regex must not be null"); return asList(item.split(regex)); } /** * Get all item's (in iteration order) from a collection except the first. * The collection must contain at least one item or an * {@link jedi.assertion.AssertionError AssertionError} will be thrown. * * @return all items except the first * @throws jedi.assertion.AssertionError * if the collection contains less or more than one item * @see #only(Collection) * @see #headOrNullIfEmpty(Iterable) * @see #headOrDefaultIfEmpty(Iterable, Object) */ public static List tail(final Iterable items) { assertNotNull(items, "items must not be null"); assertTrue(hasItems(items), "items must not be empty"); return drop(1, items); } /** * Get the first n elements of items. * * @see SRFI-1 */ public static List take(final int n, final Iterable items) { assertNotNull(items, "list must not be null"); List result = new ArrayList(); for (T item : items) { if (result.size() == n) { return result; } result.add(item); } assertEqual(n, result.size(), "There are not enough items to take"); return result; } /** * Get the last n elements of an Iterable. * * @see SRFI-1 */ public static List takeRight(final int n, final Iterable items) { assertNotNull(items, "list must not be null"); List asList = toList(items); assertLessThanOrEqualTo(asList.size(), n, "n must be less than or equal to list.size"); return drop(asList.size() - n, asList); } /** * Get n middle elements of an Iterable. */ public static List takeMiddle(final int start, final int n, final Iterable items) { assertNotNull(items, "list must not be null"); assertGreaterThanOrEqualTo(0, start, "start must not be negative"); assertGreaterThanOrEqualTo(0, n, "n must not be negative"); List result = new ArrayList(); int index = 0; for (T item : items) { if (result.size() == n) { return result; } if (index >= start) { result.add(item); } index++; } assertEqual(n, result.size(), "The given items has insufficient elements"); return result; } /** * Zip interleaves a collection of lists. If zip is passed n lists, it * returns a list as long as the shortest of these lists, each element of * which is an n-element list comprised of the corresponding elements from * the parameter lists. * *

* See SRFI-1 * * @param lists * @return zipped lists */ public static List zip(final Iterable lists) { final int n = shortest(lists).size(); final List result = new ArrayList(); for (int i = 0; i < n; i++) { result.add(slice(i, lists)); } return result; } /** * Zips two lists returning a List of Tuple2. * The returned list's length is the smallest of listA and listB */ public static List> zip(final List listA, final List listB) { final int n = shortest(list(listA, listB)).size(); final List> result = new ArrayList>(); for (int i = 0; i < n; i++) { result.add(Tuples.pair(listA.get(i), listB.get(i))); } return result; } /** * ZipWithIndex Zips this list with its indices. * For example list("a", "b", "c").zipWithIndex = List(("a", 0), ("b", 1), ("c", 2)) * where (x,y) is a {@link Tuple2}. * @return a list of Tuple2 containing elements of list and their index in the list. */ public static List> zipWithIndex(final List list) { final List> result = new ArrayList>(); for (int i = 0; i < list.size(); i++) { result.add(new Tuple2(list.get(i), i)); } return result; } /** * @return a list of lists by splitting the given list into lists of length * length. */ public static List> tabulate(final Iterable list, int length) { List line = toList(list); assertTrue(line.size() % length == 0, "size must be a multiple of length", line, length); List> result = new ArrayList>(line.size()); for (int i = 0; i < line.size(); i += length) { result.add(takeMiddle(i, length, line)); } return result; } /** * Removes the last item (in iteration order) from a collection. * The collection must contain at least one item or an * {@link jedi.assertion.AssertionError AssertionError} will be thrown. * Emulates Array.pop in Ruby. * * The original collection is unaltered. * * @return the last item in the collection * @throws jedi.assertion.AssertionError * if the collection is empty * @see #only(Collection) * @see #headOrNullIfEmpty(Iterable) * @see #headOrDefaultIfEmpty(Iterable, Object) */ public static T pop(Iterable items) { List list = toList(items); assertNotNullOrEmpty(list, "items must not be null or empty"); return list.remove(list.size() - 1); } /** * Removes the last item (in iteration order) from a collection as an * {@link Option}. * * @return the last item in the collection as {@link Some} or {@link None} * if the list is empty. */ public static Option popOption(Iterable items) { return isEmpty(items) ? Options. none() : some(pop(items)); } /** * Partition a collection of items into two sublists using the given filter. * * @param items * @return a list whose first element as a list of items in list that pass * the filter, the second item is a list of elements that did not * pass the filter. */ public static Tuple2, List> partition(Iterable items, Filter filter) { return pair(select(items, filter), select(items, invert(filter))); } /** * Return the set of all subsets of the provided collection. * *

For example, if all is the list ("x","y","z"), the return will be set containing * 8 lists as follows:

* *
    *
  • () - empty set
  • *
  • ("x")
  • *
  • ("y")
  • *
  • ("z")
  • *
  • ("x","y")
  • *
  • ("x","z")
  • *
  • ("y","z")
  • *
  • ("x","y","z")
  • *
* *

See http://en.wikipedia.org/wiki/Power_set

* * @see #powerset(Collection, Command) * @see #foldPowerset(Object, Collection, Functor2) * */ public static Set> powerset(Collection all) { assertNotNull(all, "all must not be null"); return all.isEmpty() ? set(Collections.emptyList()) : nonDegeneratePowerSet(all); } private static Set> nonDegeneratePowerSet(Collection all) { Set> powerset = new HashSet>(); int howManySubsetsInThePowerSet = 2 << (all.size() - 1); for(int i = 0 ; i != howManySubsetsInThePowerSet ; i++) { List currentSubset = createSubsetFromOriginalSet(all, i); powerset.add(currentSubset); } return powerset; } private static List createSubsetFromOriginalSet(Iterable all, int elementsToIncludeBitMap) { List current = new ArrayList(); int remainingElementsToInclude = elementsToIncludeBitMap; for (T t : all) { if ((remainingElementsToInclude & 1) == 1) { current.add(t); } remainingElementsToInclude >>= 1; } return current; } /** * Iterate all powersets of the give collection, in no particular order. * @see #powerset(Collection) * @see #foldPowerset(Object, Collection, Functor2) */ public static void powerset(Collection all, Command> command) { assertNotNull(all, "all must not be null"); assertNotNull(command, "command must not be null"); recursePowerset(Collections.emptyList(), asList(all), command); } private static void recursePowerset(List prefix, List tail, Command> command) { command.execute(prefix); for (int i = 0 ; i < tail.size() ; i++) { recursePowerset(append(prefix, list(tail.get(i))), tail.subList(i + 1, tail.size()), command); } } /** * Fold over all powersets of the give collection, in no particular order. * @see #powerset(Collection) * @see #powerset(Collection, Command) * @see #fold(Object, Iterable, Functor2) */ public static R foldPowerset(I initialValue, Collection all, final Functor2, R> functor2) { assertNotNull(all, "all must not be null"); assertNotNull(functor2, "functor2 must not be null"); return recursePowerset(initialValue, Collections.emptyList(), asList(all), functor2); } private static R recursePowerset(I initialValue, List prefix, List tail, final Functor2, R> functor2) { R value = functor2.execute(initialValue, prefix); for (int i = 0 ; i < tail.size() ; i++) { value = recursePowerset(value, append(prefix, list(tail.get(i))), tail.subList(i + 1, tail.size()), functor2); } return value; } /** * Builds a new collection by applying a function to all elements of list and concatenating the results. *

Synonymous with {@link #flatten(Iterable, Functor)} * @param iter the collection to map * @param functor a functor yielding a collection from the application of an element from iter * @return a flattened List */ public static List flatMap(Iterable iter, final Functor> functor) { return flatten(iter, functor); } /** * Curries f2 with f0 returning a functor taking a single argument. * For example, given a Functor2, f2, that sums its integer arguments, and a Functor0, f0, that returns 3, * curry(f2, f0) gives a Functor that accepts a single integer, v, and returns 3 + v. *

f0 needn't be a constant, it could be any function that returns an appropriate result for f2's consumption. * @param f2 * @param f0 */ public static ComposeableFunctor curry(final Functor2 f2, final Functor0 f0) { return composeable(new Functor() { public R execute(U value) { return f2.execute(f0.execute(), value); } }); } /** * Find the 0-based index of the first value of a collection satisfying the filter. * @param all * @param filter * @param * @return the 0-based index of the first value of a all satisfying filter or -1 */ public static int indexWhere(Iterable all, final Filter filter) { int c = 0; for (T t : all) { if (filter.execute(t)) return c; c += 1; } return -1; } /** * Find the 0-based index of the last value of a collection satisfying the filter. * @param all * @param filter * @param * @return the 0-based index of the last value of a all satisfying filter or -1 */ public static int lastIndexWhere(Iterable all, final Filter filter) { List reversed = reverse(all); int i = indexWhere(reversed, filter); return i == -1 ? -1 : reversed.size() -1 - i; } }