package org.enumerable.lambda.enumerable;
import static org.enumerable.lambda.enumerable.collection.EnumerableModule.*;
import static org.enumerable.lambda.exception.UncheckedException.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.enumerable.lambda.Fn0;
import org.enumerable.lambda.Fn1;
import org.enumerable.lambda.Fn2;
import org.enumerable.lambda.enumerable.collection.EList;
import org.enumerable.lambda.enumerable.collection.EMap;
import org.enumerable.lambda.enumerable.collection.ESet;
import org.enumerable.lambda.enumerable.collection.EnumerableModule;
import org.enumerable.lambda.enumerable.collection.IEnumerable;
/**
* Ruby/Smalltalk style internal iterators for Java 5 using bytecode
* transformation to capture expressions as closures.
*
* <p>
* <a href="http://ruby-doc.org/core/classes/Enumerable.html"/>Ruby's Enumerable
* module in 1.8.6</a>
* </p>
* <p>
* <a href="http://ruby-doc.org/ruby-1.9/classes/Enumerable.html"/>Ruby's
* Enumerable module in 1.9</a>
* </p>
*
* This class is as a facade for the implementation of the in
* {@link EnumerableModule} and {@link EMap}.
*/
@SuppressWarnings({"unchecked"})
public class Enumerable {
/**
* Passes each element of the collection to the given block. The method
* returns true if the block never returns false or null.
*/
public static <E> boolean all(Iterable<E> collection, Fn1<? super E, ?> block) {
return extend(collection).all(block);
}
/**
* Passes each element of the collection to the an implicit block of
* {@link Fn1#identity()}. The method returns true if the block never
* returns false or null.
*/
public static <E> boolean all(Iterable<E> collection) {
return extend(collection).all();
}
/**
* Passes each element of the collection to the given block. The method
* returns true if the block ever returns a value other than false or null.
*/
public static <E> boolean any(Iterable<E> collection, Fn1<? super E, ?> block) {
return extend(collection).any(block);
}
/**
* Passes each element of the collection to the an implicit block of
* {@link Fn1#identity()}. The method returns true if the block ever returns
* a value other than false or null.
*/
public static <E> boolean any(Iterable<E> collection) {
return extend(collection).any();
}
/**
* Returns a new list with the results of running block once for every
* element in collection.
*/
public static <E, R> EList<R> collect(Iterable<E> collection, Fn1<? super E, ? extends R> block) {
return extend(collection).collect(block);
}
/**
* Returns the count of all elements in collection.
*/
public static <E> int count(Iterable<E> collection) {
return extend(collection).count();
}
/**
* Returns the count of objects in collection that equal obj.
*/
public static <E> int count(Iterable<E> collection, E obj) {
return extend(collection).count(obj);
}
/**
* Returns the count of objects in collection for which the block returns a
* true value.
*/
public static <E> int count(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).count(block);
}
/**
* Returns null if collection has no elements; otherwise, passes the
* elements, one at a time to the block. When it reaches the end, it
* repeats. The number of times it repeats is set by the parameter.
*/
public static <E, R> EList<E> cycle(Iterable<E> collection, int times, Fn1<? super E, R> block) {
return extend(collection).cycle(times, block);
}
/**
* Passes each entry in collection to block. Returns the first for which
* block is not false. If no object matches, it returns null.
*/
public static <E> E detect(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return (E) extend(collection).detect(block);
}
/**
* Passes each entry in collection to block. Returns the first for which
* block is not false. If no object matches, it returns ifNone.
*/
public static <E> E detect(Iterable<E> collection, Fn0<E> ifNone, Fn1<? super E, Boolean> block) {
return (E) extend(collection).detect(ifNone, block);
}
/**
* Returns a list containing all but the first n elements of collection.
*/
public static <E> EList<E> drop(Iterable<E> collection, int n) {
return extend(collection).drop(n);
}
/**
* Passes elements in turn to the block until the block does not return a
* true value. Starting with that element, copies the remainder to a list
* and returns it.
*/
public static <E> EList<E> dropWhile(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).dropWhile(block);
}
/**
* Calls block for each item in collection.
*/
public static <E, R> IEnumerable<E> each(Iterable<E> collection, Fn1<? super E, R> block) {
return extend(collection).each(block);
}
/**
* Calls block once for each key in map, passing the key and value to the
* block as parameters.
*/
public static <K, V, R> EMap<K, V> each(Map<K, V> map, Fn2<? super K, ? super V, R> block) {
return extend(map).each(block);
}
/**
* Iterates the given block for each list of consecutive n elements.
*/
public static <E, R> Object eachCons(Iterable<E> collection, int n, Fn1<List<E>, R> block) {
return extend(collection).eachCons(n, block);
}
/**
* Calls block once for each key in map, passing the key as parameter.
*/
public static <K, V, R> EMap<K, V> eachKey(Map<K, V> map, Fn1<? super K, ? super R> block) {
return extend(map).eachKey(block);
}
/**
* Executes the block for every line in file.
*/
public static <R> File eachLine(File file, Fn1<String, R> block) {
try {
eachLine(new FileReader(file), block);
return file;
} catch (FileNotFoundException e) {
throw uncheck(e);
}
}
/**
* Executes the block for every line in reader.
*/
public static <R> Reader eachLine(Reader reader, Fn1<String, R> block) {
try {
BufferedReader in = new BufferedReader(reader);
String line;
while ((line = in.readLine()) != null)
block.call(line);
return reader;
} catch (IOException e) {
throw uncheck(e);
} finally {
try {
reader.close();
} catch (IOException silent) {
}
}
}
/**
* Executes the block for every line in string.
*/
public static <R> String eachLine(String string, Fn1<String, R> block) {
eachLine(new StringReader(string), block);
return string;
}
/**
* Iterates the given block for each slice of n elements.
*/
public static <E, R> Object eachSlice(Iterable<E> collection, int n, Fn1<List<E>, R> block) {
return extend(collection).eachSlice(n, block);
}
/**
* Calls block once for each value in map, passing the key as parameter.
*/
public static <K, V, R> EMap<K, V> eachValue(Map<K, V> map, Fn1<? super V, ? super R> block) {
return extend(map).eachValue(block);
}
/**
* Calls block with two arguments, the item and its index, for each item in
* collection.
*/
public static <E, R> IEnumerable<E> eachWithIndex(Iterable<E> collection, Fn2<? super E, Integer, R> block) {
return extend(collection).eachWithIndex(block);
}
/**
* Calls block with two arguments, the item and the memo object, for each
* item in collection.
*/
public static <E, M, R> M eachWithObject(Iterable<E> collection, M memo, Fn2<? super E, M, R> block) {
return (M) extend(collection).eachWithObject(memo, block);
}
/**
* @see #toList(Iterable)
*/
public static <E> EList<E> entries(Iterable<E> collection) {
return extend(collection).toList();
}
/**
* @see #detect(Iterable, Fn1)
*/
public static <E> E find(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return (E) extend(collection).find(block);
}
/**
* @see #detect(Iterable, Fn0, Fn1)
*/
public static <E> E find(Iterable<E> collection, Fn0<E> ifNone, Fn1<? super E, Boolean> block) {
return (E) extend(collection).find(ifNone, block);
}
/**
* @see #select(Iterable, Fn1)
*/
public static <E> EList<E> findAll(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).findAll(block);
}
/**
* Returns the index of the first item for which the given block returns a
* true value or returns -1 if the block only ever returns false.
*/
public static <E> int findIndex(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).findIndex(block);
}
/**
* Returns the first item of collection or null.
*/
public static <E> E first(Iterable<E> collection) {
return (E) extend(collection).first();
}
/**
* Returns the first n items of collection.
*/
public static <E> EList<E> first(Iterable<E> collection, int n) {
return extend(collection).first(n);
}
/**
* Returns a list of every element in collection for which pattern matches.
*/
public static <E> EList<E> grep(Iterable<E> collection, Pattern pattern) {
return extend(collection).grep(pattern);
}
/**
* Returns a list of every element in collection for which pattern matches.
* Each matching element is passed to tje block, and its result is stored in
* the output list.
*/
public static <E, R> EList<R> grep(Iterable<E> collection, Pattern pattern, Fn1<? super E, R> block) {
return extend(collection).grep(pattern, block);
}
/**
* @see #grep(Iterable, Pattern)
*/
public static <E> EList<E> grep(Iterable<E> collection, String pattern) {
return extend(collection).grep(pattern);
}
/**
* @see #grep(Iterable, Pattern, Fn1)
*/
public static <E, R> EList<R> grep(Iterable<E> collection, String pattern, Fn1<? super E, R> block) {
return extend(collection).grep(pattern, block);
}
/**
* Partitions collection by calling the block for each item and using the
* result returned by the block to group the items into buckets. Returns a
* map where the keys are the objects returned by the block, and the values
* for a key are those items for which the block returned that object.
*/
public static <E, R> EMap<R, EList<E>> groupBy(Iterable<E> collection, Fn1<? super E, R> block) {
return extend(collection).groupBy(block);
}
/**
* Named parameter for detect.
*
* @see #detect(Iterable, Fn0, Fn1)
* @see #find(Iterable, Fn0, Fn1)
*/
public static <R> Fn0<R> ifNone(R defaultValue) {
return Fn0.constant(defaultValue);
}
/**
* @see #member(Iterable, Object)
*/
public static <E> boolean include(Iterable<E> collection, Object obj) {
return extend(collection).include(obj);
}
/**
* Combines the elements of collection by applying the block to an
* accumulator value (memo) and each element in turn. At each step, memo is
* set to the value returned by the block. This form uses the first element
* of the collection as a the initial value (and skips that element while
* iterating).
*/
public static <E> E inject(Iterable<E> collection, Fn2<? super E, ? super E, ? extends E> block) {
return (E) extend(collection).inject(block);
}
/**
* Combines the elements of collection by applying the block to an
* accumulator value (memo) and each element in turn. At each step, memo is
* set to the value returned by the block. This form lets you supply an
* initial value for memo.
*/
public static <E, R> R inject(Iterable<E> collection, R initial, Fn2<? super R, ? super E, ? extends R> block) {
return (R) extend(collection).inject(initial, block);
}
/**
* @see #collect(Iterable, Fn1)
*/
public static <E, R> EList<R> map(Iterable<E> collection, Fn1<? super E, ? extends R> block) {
return extend(collection).map(block);
}
/**
* Returns the object in collection with the maximum value. This form
* assumes all objects implement {@link Comparable}
*/
public static <E extends Object & Comparable<? super E>> E max(Iterable<E> collection) {
return (E) extend(collection).max();
}
/**
* Returns the object in collection with the maximum value. This form uses
* the block to {@link Comparator#compare}.
*/
public static <E> E max(Iterable<E> collection, Fn2<? super E, ? super E, Integer> block) {
return (E) extend(collection).max(block);
}
/**
* Passes each item in the collection to the block. Returns the item
* corresponding to the largest value returned by the block.
*/
public static <E, R extends Object & Comparable<? super R>> E maxBy(Iterable<E> collection,
Fn1<? super E, R> block) {
return (E) extend(collection).maxBy(block);
}
/**
* Returns true if any member of collection equals obj. Equality is tested
* using {@link Object#equals(Object)}.
*/
public static <E> boolean member(Iterable<E> collection, Object obj) {
return extend(collection).include(obj);
}
/**
* Returns the object in collection with the minimum value. This form
* assumes all objects implement {@link Comparable}.
*/
public static <E extends Object & Comparable<? super E>> E min(Iterable<E> collection) {
return (E) extend(collection).min();
}
/**
* Returns the object in collection with the minimum value. This form uses
* the block to {@link Comparator#compare}.
*/
public static <E> E min(Iterable<E> collection, Fn2<? super E, ? super E, Integer> block) {
return (E) extend(collection).min(block);
}
/**
* Passes each item in the collection to the block. Returns the item
* corresponding to the smallest value returned by the block.
*/
public static <E, R extends Object & Comparable<? super R>> E minBy(Iterable<E> collection,
Fn1<? super E, R> block) {
return (E) extend(collection).minBy(block);
}
/**
* Compares the elements of collection using {@link Comparable}, returning
* the minimum and maximum value.
*/
public static <E extends Object & Comparable<? super E>> EList<E> minMax(Iterable<E> collection) {
return extend(collection).minMax();
}
/**
* Compares the elements of collection using the given block, returning the
* minimum and maximum value.
*/
public static <E> EList<E> minMax(Iterable<E> collection, Fn2<? super E, ? super E, Integer> block) {
return extend(collection).minMax(block);
}
/**
* Passes each item in the collection to the block. Returns the items
* corresponding to the smallest and largest values returned by the block.
*/
public static <E, R extends Object & Comparable<? super R>> EList<E> minMaxBy(Iterable<E> collection,
Fn1<? super E, R> block) {
return extend(collection).minMaxBy(block);
}
/**
* Passes each element of the collection to the given block. The method
* returns true if the block never returns a value other than false or null.
*/
public static <E> boolean none(Iterable<E> collection, Fn1<? super E, ?> block) {
return extend(collection).none(block);
}
/**
* Passes each element of the collection to the an implicit block of
* {@link Fn1#identity()}. The method returns true if the block never
* returns a value other than false or null.
*/
public static <E> boolean none(Iterable<E> collection) {
return extend(collection).none();
}
/**
* Passes each element of the collection to the given block. The method
* returns true if the block returns true exactly one time.
*/
public static <E> boolean one(Iterable<E> collection, Fn1<? super E, ?> block) {
return extend(collection).one(block);
}
/**
* Passes each element of the collection to the an implicit block of
* {@link Fn1#identity()}. The method returns true if the block returns true
* exactly one time.
*/
public static <E> boolean one(Iterable<E> collection) {
return extend(collection).one();
}
/**
* Returns two lists, the first containing the elements of collection for
* which the block evaluates to true, the second containing the rest.
*/
public static <E> EList<EList<E>> partition(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).partition(block);
}
/**
* Constructs a range using the given start and end. The range will include
* the end object.
*/
public static Range range(int start, int end) {
return range(start, end, false);
}
/**
* Constructs a range using the given start and end. If the third parameter
* is false, the range will include the end object; otherwise, it will be
* excluded.
*/
public static Range range(int start, int end, boolean exclusive) {
return new Range(start, end, exclusive);
}
/**
* @see #inject(Iterable, Fn2)
*/
public static <E> E reduce(Iterable<E> collection, Fn2<? super E, ? super E, ? extends E> block) {
return (E) extend(collection).reduce(block);
}
/**
* @see #inject(Iterable, Object, Fn2)
*/
public static <E, R> R reduce(Iterable<E> collection, R initial, Fn2<? super R, ? super E, ? extends R> block) {
return (R) extend(collection).reduce(initial, block);
}
/**
* Returns a list containing all elements of collection for which block is
* false.
*/
public static <E> EList<E> reject(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).reject(block);
}
/**
* Invokes the block with the elements of collection in reverse order.
* Creates an intermediate list internally, so this might be expensive on
* large collections.
*/
public static <E, R> IEnumerable<E> reverseEach(Iterable<E> collection, Fn1<? super E, R> block) {
return extend(collection).reverseEach(block);
}
/**
* Returns a list containing all elements of collection for which block is
* not false.
*/
public static <E> EList<E> select(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).select(block);
}
/**
* Returns a list containing all Map.Entry pairs for which the block returns
* true.
*/
public static <K, V> EList<Map.Entry<K, V>> select(Map<K, V> map, Fn2<? super K, ? super V, Boolean> block) {
return extend(map).select(block);
}
/**
* Returns a list containing the items in collection sorted, according to
* their own compareTo method.
*/
public static <E extends Object & Comparable<? super E>> EList<E> sort(Iterable<E> collection) {
return extend(collection).sort();
}
/**
* Returns a list containing the items in collection sorted by using the
* results of the supplied block.
*/
public static <E> EList<E> sort(Iterable<E> collection, Fn2<? super E, ? super E, Integer> block) {
return extend(collection).sort(block);
}
/**
* Sorts collection using a set of keys generated by mapping the values in
* collection through the given block.
* <p>
* The current implementation of sortBy generates an array of tuples
* containing the original collection element and the mapped value. This
* makes sortBy fairly expensive when the keysets are simple
* <p>
* However, consider the case where comparing the keys is a non-trivial
* operation. The following code sorts some files on modification time.
*
* <pre>
* sortBy(files, fn(s, new File(s).lastModified()) // ["mon", "tues", "wed", "thurs"]
* </pre>
* <p>
* Perl users often call this approach a Schwartzian Transform, after Randal
* Schwartz. We construct a temporary array, where each element is an array
* containing our sort key along with the filename. We sort this array, and
* then extract the filename from the result.
*/
public static <E, R extends Object & Comparable<? super R>> EList<E> sortBy(Iterable<E> collection,
Fn1<? super E, R> block) {
return extend(collection).sortBy(block);
}
/**
* Returns a list containing the first n items from collection.
*/
public static <E> EList<E> take(Iterable<E> collection, int n) {
return extend(collection).take(n);
}
/**
* Passes successive items to the block, adding them to the result list
* until the block returns false or null.
*/
public static <E> EList<E> takeWhile(Iterable<E> collection, Fn1<? super E, Boolean> block) {
return extend(collection).takeWhile(block);
}
/**
* @see #times(int, Fn1)
*/
public static int times(int i, Fn0<?> block) {
Iterator<Integer> range = range(0, i, true).iterator();
for (; range.hasNext(); range.next())
block.call();
return i;
}
/**
* Iterates block i times, passing in values from zero to i - 1.
*/
public static int times(int i, Fn1<Integer, ?> block) {
each(range(0, i, true), block);
return i;
}
/**
* Returns a list containing the items in collection.
*/
public static <E> EList<E> toList(Iterable<E> collection) {
return extend(collection).toList();
}
/**
* Creates a new Set containing the elements of the given collection.
*/
public static <E> ESet<E> toSet(Iterable<E> collection) {
return extend(collection).toSet();
}
/**
* Creates a new Set containing the elements of the given collection, the
* elements are preprocessed by the given block.
*/
public static <E, R> ESet<R> toSet(Iterable<E> collection, Fn1<? super E, R> block) {
return extend(collection).toSet(block);
}
/**
* Converts any arguments to iterators, then merges elements of collection
* with corresponding elements from each argument. This generates a sequence
* of collection#size n-element list, where n is one more that the count of
* arguments. If the size of any argument is less than collection#size, null
* values are supplied. The block is invoked for each output array. Returns
* null.
*/
public static <E, R> Object zip(Iterable<E> collection, List<Iterable<?>> args, Fn1<? super EList<?>, R> block) {
return extend(collection).zip(args, block);
}
/**
* Converts any arguments to iterators, then merges elements of collection
* with corresponding elements from each argument. This generates a sequence
* of collection#size n-element list, where n is one more that the count of
* arguments. If the size of any argument is less than collection#size, null
* values are supplied.
*/
public static <E> EList<EList<?>> zip(Iterable<E> collection, Iterable<?>... args) {
return extend(collection).zip(args);
}
}