package com.googlecode.totallylazy.transducers; import com.googlecode.totallylazy.Option; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.functions.Function2; import com.googlecode.totallylazy.functions.Reducer; import com.googlecode.totallylazy.predicates.Predicate; import java.util.Iterator; import java.util.List; import static com.googlecode.totallylazy.Sequences.sequence; import static com.googlecode.totallylazy.functions.Functions.identity; public interface Sender<A> { AutoCloseable EMPTY_CLOSEABLE = () -> { }; AutoCloseable send(Receiver<A> receiver); @SafeVarargs static <A> Sender<A> sender(A... values) { return sender(sequence(values)); } static <A> Sender<A> sender(Iterable<? extends A> values) { return sender(values.iterator()); } static <A> Sender<A> sender(Iterator<? extends A> iterator) { return new IteratorSender<>(iterator); } default Sender<A> filter(Predicate<? super A> predicate) { return transduce(Transducers.filter(predicate)); } default Sender<A> find(Predicate<? super A> predicate) { return transduce(Transducers.find(predicate)); } default <B> Sender<B> map(Function1<? super A, ? extends B> mapper) { return transduce(Transducers.map(mapper)); } default <B> Sender<B> flatMap(Function1<? super A, ? extends Sender<B>> mapper) { return transduce(Transducers.flatMap(mapper)); } static <B> Sender<B> flatten(Sender<Sender<B>> nested) { return nested.flatMap(identity()); } default <B> Sender<B> scan(B seed, Function2<? super B, ? super A, ? extends B> reducer) { return transduce(Transducers.scan(seed, reducer)); } default <B> Sender<B> scan(Reducer<? super A, B> reducer) { return transduce(Transducers.scan(reducer)); } default Sender<A> first() { return transduce(Transducers.first()); } default Sender<Option<A>> firstOption() { return transduce(Transducers.firstOption()); } default Sender<A> last() { return transduce(Transducers.last()); } default Sender<Option<A>> lastOption() { return transduce(Transducers.lastOption()); } default <B> Sender<B> reduce(B seed, Function2<? super B, ? super A, ? extends B> reducer) { return transduce(Transducers.reduce(seed, reducer)); } default <B> Sender<B> reduce(Reducer<? super A, B> reducer) { return transduce(Transducers.reduce(reducer)); } default Sender<A> take(int limit) { return transduce(Transducers.take(limit)); } default Sender<A> takeWhile(Predicate<? super A> predicate) { return transduce(Transducers.takeWhile(predicate)); } default Sender<A> drop(int count) { return transduce(Transducers.drop(count)); } default Sender<A> dropWhile(Predicate<? super A> predicate) { return transduce(Transducers.dropWhile(predicate)); } default <B> Sender<Group<B, A>> groupBy(Function1<? super A, ? extends B> keyExtractor) { return transduce(Transducers.groupBy(keyExtractor)); } default <B> Sender<B> transduce(Transducer<A, B> transducer) { return transduce(this, transducer); } static <A, B> Sender<B> transduce(Sender<A> sender, Transducer<A, B> transducer) { return CompositeSender.compositeSender(sender, transducer); } default Sender<List<A>> toList() { return transduce(Transducers.toList()); } default Sender<Sequence<A>> toSequence() { return transduce(Transducers.toSequence()); } }