}));
}
public static Iterable> zip(final Iterable firstIterable, final Iterable secondIterable) {
return new Iterable>(){
public Iterator> iterator() {
return new TwoZippedIterator(firstIterable.iterator(), secondIterable.iterator());
}
};
}
public static Iterable> zip(Iterable firstIterable, Iterable secondIterable, Iterable thirdIterable) {
return map(zip(listWith(firstIterable, secondIterable, thirdIterable)), Lazy.toTriple());
}
@SuppressWarnings("unchecked")
private static Mapper, Triple> toTriple() {
return new Mapper, Triple>() {
@Override public Triple map(Iterable> iterable) {
return tuple((R) first(iterable), (S) first(rest(iterable)), (T) first(rest(rest(iterable))));
}
};
}
public static Iterable extends Iterable>> zip(final Iterable extends Iterable>> iterables) {
return new Iterable>() {
public Iterator> iterator() {
final Iterable> iterators = Eager.map(iterables, toIterators());
return new Iterator>() {
public boolean hasNext() {
return Eager.all(iterators, new Predicate>(){
public boolean evaluate(Iterator> iterator) {
return iterator.hasNext();
}
});
}
public Iterable> next() {
if (hasNext()) {
return Eager.map(iterators, new Mapper, Object>() {
public Object map(Iterator> iterator) {
return iterator.next();
}
});
} else {
throw new NoSuchElementException();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
private static Mapper, Iterator extends T>> toIterators() {
return new Mapper, Iterator extends T>>() {
@Override public Iterator extends T> map(Iterable extends T> iterable) {
return iterable.iterator();
}
};
}
public static Iterable extends Triple> cartesianProduct(
Iterable first, Iterable second, Iterable third) {
return map(cartesianProduct(listWith(first, second, third)), Mappers.toTriple());
}
public static Iterable extends Quadruple> cartesianProduct(
Iterable first, Iterable second, Iterable third, Iterable fourth) {
return map(cartesianProduct(listWith(first, second, third, fourth)), Mappers.toQuadruple());
}
private static Iterable extends Iterable>> cartesianProduct(final Iterable extends Iterable>> iterables) {
return cartesianProduct(listFrom(iterables));
}
private static Iterable extends Iterable>> cartesianProduct(final List> iterables) {
if(iterables.size() == 2) {
return cartesianProduct(first(iterables), second(iterables));
}
@SuppressWarnings("unchecked")
Iterable>> pairs = cartesianProduct(
(Iterable |