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

cyclops.data.ImmutableQueue Maven / Gradle / Ivy

There is a newer version: 10.4.1
Show newest version
package cyclops.data;

import com.oath.cyclops.types.foldable.Contains;
import com.oath.cyclops.types.persistent.PersistentCollection;
import com.oath.cyclops.types.persistent.PersistentQueue;
import com.oath.cyclops.matching.Deconstruct.Deconstruct2;
import com.oath.cyclops.matching.Sealed2;
import com.oath.cyclops.types.foldable.To;
import com.oath.cyclops.types.recoverable.OnEmptyError;
import com.oath.cyclops.types.recoverable.OnEmptySwitch;
import com.oath.cyclops.types.traversable.IterableX;
import com.oath.cyclops.types.traversable.Traversable;
import cyclops.control.Option;
import cyclops.control.Try;
import cyclops.function.Function3;
import cyclops.function.Function4;
import cyclops.function.Monoid;

import cyclops.reactive.ReactiveSeq;
import cyclops.data.tuple.Tuple;
import cyclops.data.tuple.Tuple2;
import cyclops.data.tuple.Tuple3;
import cyclops.data.tuple.Tuple4;
import org.reactivestreams.Publisher;

import java.util.*;
import java.util.function.*;
import java.util.stream.Stream;


public interface ImmutableQueue extends Sealed2,ImmutableQueue.None>,
                                            OnEmptySwitch, ImmutableQueue>,
                                            OnEmptyError>,
                                            Contains,
                                            IterableX, To>, PersistentQueue {



    @Override
    default ImmutableQueue plus(T e){
        return append(e);
    }

    @Override
    default ImmutableQueue removeValue(T value) {
        return removeFirst(e->Objects.equals(e,value));
    }

    @Override
    default ImmutableQueue plusAll(Iterable list){
        ImmutableQueue set = this;
        for(T next : list){
            set = set.plus(next);
        }
        return set;
    }


     ImmutableQueue unitStream(Stream stream);
     ImmutableQueue unitIterable(Iterable it);

    ImmutableQueue emptyUnit();

    default ImmutableQueue replace(T currentElement, T newElement){
        ImmutableQueue preceding = emptyUnit();
        ImmutableQueue tail = this;
        while(!tail.isEmpty()){
            ImmutableQueue ref=  preceding;
            ImmutableQueue tailRef = tail;
            Tuple3, ImmutableQueue, Boolean> t3 = tail.fold(c -> {
                if (Objects.equals(c.head(), currentElement))
                    return Tuple.tuple(ref, tailRef, true);
                return Tuple.tuple(ref.prepend(c.head()), c.tail(), false);
            }, nil -> Tuple.tuple(ref, tailRef, true));

            preceding = t3._1();
            tail = t3._2();
            if(t3._3())
                break;

        }

        ImmutableQueue start = preceding;
        return tail.fold(cons->cons.tail().prepend(newElement).prependAll(start), nil->this);
    }
    default ImmutableQueue removeFirst(Predicate pred){
        ImmutableQueue res[] = new ImmutableQueue[]{emptyUnit()};
        ImmutableQueue rem = this;
        boolean[] found = {false};
        do {
            rem = rem.fold(s -> {
                return s.fold((head, tail2) -> {
                    found[0] = pred.test(head);
                    if(!found[0]) {
                        res[0] = res[0].prepend(head);
                        return tail2;
                    }
                    return tail2;
                });
            }, n -> n);
        }while(!rem.isEmpty() && !found[0]);

        ImmutableQueue ar = rem.fold(s -> s.fold((h, t) -> t), n -> n);
        return res[0].foldLeft(ar, (a,b)->a.prepend(b));

    }


    default ImmutableQueue subList(int start, int end){
        return drop(start).take(end-start);
    }
    default LazySeq lazySeq(){

        return fold(c->LazySeq.lazy(c.head(),()->c.tail().lazySeq()), nil->LazySeq.empty());
    }
    default Seq imSeq(){

        return fold(c->Seq.cons(c.head(),c.tail().imSeq()), nil->Seq.empty());
    }

    default Tuple2, ImmutableQueue> partition(final Predicate splitter) {

        return Tuple.tuple(filter(splitter), filter(splitter.negate()));

    }
    default Tuple2, ImmutableQueue> span(Predicate pred) {
        return Tuple.tuple(takeWhile(pred), dropWhile(pred));
    }

    default Tuple2,ImmutableQueue> splitBy(Predicate test) {
        return span(test.negate());
    }


    default Tuple2, ImmutableQueue> splitAt(int n) {
        return Tuple.tuple(take(n), drop(n));
    }

    default Zipper focusAt(int pos, T alt){
        Tuple2, ImmutableQueue> t2 = splitAt(pos);
        T value = t2._2().fold(c -> c.head(), n -> alt);
        ImmutableQueue right= t2._2().fold(c->c.tail(), n->null);
        return Zipper.of(t2._1().lazySeq(),value, right.lazySeq());
    }
    default Option> focusAt(int pos){
        Tuple2, ImmutableQueue> t2 = splitAt(pos);
        Option value = t2._2().fold(c -> Option.some(c.head()), n -> Option.none());
        return value.map(l-> {
            ImmutableQueue right = t2._2().fold(c -> c.tail(), n -> null);
            return Zipper.of(t2._1().lazySeq(), l, right.lazySeq());
        });
    }

    ImmutableQueue drop(long num);
    ImmutableQueue take(long num);


    ImmutableQueue prepend(T value);
    ImmutableQueue prependAll(Iterable value);

    ImmutableQueue append(T value);
    ImmutableQueue appendAll(Iterable value);

    ImmutableQueue reverse();

    Option get(int pos);
    T getOrElse(int pos, T alt);
    T getOrElseGet(int pos, Supplier alt);
    int size();
    default boolean containsValue(T value){
        return stream().filter(o-> Objects.equals(value,o)).findFirst().isPresent();
    }
    boolean isEmpty();

    @Override
    default  ImmutableQueue ofType(Class type) {
        return (ImmutableQueue)IterableX.super.ofType(type);
    }

    @Override
    default ImmutableQueue filterNot(Predicate predicate) {
        return (ImmutableQueue)IterableX.super.filterNot(predicate);
    }

    @Override
    default ImmutableQueue notNull() {
        return (ImmutableQueue)IterableX.super.notNull();
    }

    @Override
    ReactiveSeq stream();


    @Override
    ImmutableQueue filter(Predicate fn);


    @Override
     ImmutableQueue map(Function fn);

    @Override
    default ImmutableQueue peek(Consumer c) {
        return (ImmutableQueue)IterableX.super.peek(c);
    }



     ImmutableQueue flatMap(Function> fn);
     ImmutableQueue concatMap(Function> fn);
    @Override
     ImmutableQueue mergeMap(Function> fn);

    @Override
     ImmutableQueue mergeMap(int maxConcurecy, Function> fn);
    @Override
     R fold(Function, ? extends R> fn1, Function, ? extends R> fn2);
    @Override
    default Iterator iterator() {
        return new Iterator() {
            ImmutableQueue current= ImmutableQueue.this;
            @Override
            public boolean hasNext() {
                return current.fold(c->true, n->false);
            }

            @Override
            public T next() {
                return current.fold(c->{
                    current = c.tail();
                    return c.head();
                },n->null);
            }
        };
    }


    @Override
    ImmutableQueue onEmpty(T value);

    @Override
    ImmutableQueue onEmptyGet(Supplier supplier);

    @Override
    default  Try, X> onEmptyTry(Supplier supplier){
        return isEmpty() ? Try.failure(supplier.get()) : Try.success(this);
    }

    @Override
    ImmutableQueue onEmptySwitch(Supplier> supplier);

    public static interface Some extends Deconstruct2>, ImmutableQueue {
        T head();
        ImmutableQueue tail();
        @Override
        default  R fold(Function, ? extends R> fn1, Function, ? extends R> fn2){
            return fn1.apply(this);
        }
    }
    public interface None extends ImmutableQueue {
        @Override
        default  R fold(Function, ? extends R> fn1, Function, ? extends R> fn2){
            return fn2.apply(this);
        }

    }



    default  ImmutableQueue forEach4(Function> iterable1,
                                                       BiFunction> iterable2,
                                                       Function3> iterable3,
                                                       Function4 yieldingFunction) {

        return this.concatMap(in -> {

            ReactiveSeq a = ReactiveSeq.fromIterable(iterable1.apply(in));
            return a.flatMap(ina -> {
                ReactiveSeq b = ReactiveSeq.fromIterable(iterable2.apply(in, ina));
                return b.flatMap(inb -> {
                    ReactiveSeq c = ReactiveSeq.fromIterable(iterable3.apply(in, ina, inb));
                    return c.map(in2 -> yieldingFunction.apply(in, ina, inb, in2));
                });

            });

        });
    }

    default  ImmutableQueue forEach4(Function> iterable1,
                                                       BiFunction> iterable2,
                                                       Function3> iterable3,
                                                       Function4 filterFunction,
                                                       Function4 yieldingFunction) {

        return this.concatMap(in -> {

            ReactiveSeq a = ReactiveSeq.fromIterable(iterable1.apply(in));
            return a.flatMap(ina -> {
                ReactiveSeq b = ReactiveSeq.fromIterable(iterable2.apply(in, ina));
                return b.flatMap(inb -> {
                    ReactiveSeq c = ReactiveSeq.fromIterable(iterable3.apply(in, ina, inb));
                    return c.filter(in2 -> filterFunction.apply(in, ina, inb, in2))
                            .map(in2 -> yieldingFunction.apply(in, ina, inb, in2));
                });

            });

        });
    }


    default  ImmutableQueue forEach3(Function> iterable1,
                                                   BiFunction> iterable2,
                                                   Function3 yieldingFunction) {

        return this.concatMap(in -> {

            Iterable a = iterable1.apply(in);
            return ReactiveSeq.fromIterable(a)
                    .flatMap(ina -> {
                        ReactiveSeq b = ReactiveSeq.fromIterable(iterable2.apply(in, ina));
                        return b.map(in2 -> yieldingFunction.apply(in, ina, in2));
                    });

        });
    }


    default  ImmutableQueue forEach3(Function> iterable1,
                                                   BiFunction> iterable2,
                                                   Function3 filterFunction,
                                                   Function3 yieldingFunction) {

        return this.concatMap(in -> {

            Iterable a = iterable1.apply(in);
            return ReactiveSeq.fromIterable(a)
                    .flatMap(ina -> {
                        ReactiveSeq b = ReactiveSeq.fromIterable(iterable2.apply(in, ina));
                        return b.filter(in2 -> filterFunction.apply(in, ina, in2))
                                .map(in2 -> yieldingFunction.apply(in, ina, in2));
                    });

        });
    }


    default  ImmutableQueue forEach2(Function> iterable1,
                                               BiFunction yieldingFunction) {

        return this.concatMap(in-> {

            Iterable b = iterable1.apply(in);
            return ReactiveSeq.fromIterable(b)
                    .map(in2->yieldingFunction.apply(in, in2));
        });
    }


    default  ImmutableQueue forEach2(Function> iterable1,
                                               BiFunction filterFunction,
                                               BiFunction yieldingFunction) {

        return this.concatMap(in-> {

            Iterable b = iterable1.apply(in);
            return ReactiveSeq.fromIterable(b)
                    .filter(in2-> filterFunction.apply(in,in2))
                    .map(in2->yieldingFunction.apply(in, in2));
        });
    }

    @Override
    default ImmutableQueue removeStream(Stream stream) {
        return unitStream(stream().removeStream(stream));
    }

    default ImmutableQueue removeAll(Iterable it) {
        return unitStream(stream().removeAll(it));
    }

    @Override
    default ImmutableQueue removeAll(T... values) {
        return unitStream(stream().removeAll(values));
    }

    @Override
    default ImmutableQueue retainAll(Iterable it) {
        return unitStream(stream().retainAll(it));
    }

    @Override
    default ImmutableQueue retainStream(Stream stream) {
        return unitStream(stream().retainStream(stream));
    }

    @Override
    default ImmutableQueue retainAll(T... values) {
        return unitStream(stream().retainAll(values));
    }



    @Override
    default ImmutableQueue> permutations() {
        return unitStream(stream().permutations());
    }

    @Override
    default ImmutableQueue> combinations(int size) {
        return unitStream(stream().combinations(size));
    }

    @Override
    default ImmutableQueue> combinations() {
        return unitStream(stream().combinations());
    }

  @Override
    default  ImmutableQueue zip(BiFunction fn, Publisher publisher) {
        return unitStream(stream().zip(fn, publisher));
    }

    default  ImmutableQueue zipWithStream(Stream other, BiFunction zipper) {
        return unitStream(stream().zipWithStream(other,zipper));
    }

    @Override
    default  ImmutableQueue> zipWithPublisher(Publisher other) {
        return unitStream(stream().zipWithPublisher(other));
    }

    @Override
    default  ImmutableQueue> zip(Iterable other) {
        return unitStream(stream().zip(other));
    }

    @Override
    default  ImmutableQueue zip3(Iterable second, Iterable third, Function3 fn3) {
        return unitStream(stream().zip3(second,third,fn3));
    }

    @Override
    default  ImmutableQueue zip4(Iterable second, Iterable third, Iterable fourth, Function4 fn) {
        return unitStream(stream().zip4(second,third,fourth,fn));
    }


    @Override
    default ImmutableQueue combine(BiPredicate predicate, BinaryOperator op) {
        return unitStream(stream().combine(predicate,op));
    }

    @Override
    default ImmutableQueue combine(Monoid op, BiPredicate predicate) {
        return unitStream(stream().combine(op,predicate));
    }

    @Override
    default ImmutableQueue cycle(long times) {
        return unitStream(stream().cycle(times));
    }

    @Override
    default ImmutableQueue cycle(Monoid m, long times) {
        return unitStream(stream().cycle(m,times));
    }

    @Override
    default ImmutableQueue cycleWhile(Predicate predicate) {
        return unitStream(stream().cycleWhile(predicate));
    }

    @Override
    default ImmutableQueue cycleUntil(Predicate predicate) {
        return unitStream(stream().cycleUntil(predicate));
    }

    @Override
    default  ImmutableQueue zip(Iterable other, BiFunction zipper) {
        return unitStream(stream().zip(other,zipper));
    }

    @Override
    default  ImmutableQueue> zip3(Iterable second, Iterable third) {
        return unitStream(stream().zip3(second,third));
    }

    @Override
    default  ImmutableQueue> zip4(Iterable second, Iterable third, Iterable fourth) {
        return unitStream(stream().zip4(second,third,fourth));
    }

    @Override
    default ImmutableQueue> zipWithIndex() {
        return unitStream(stream().zipWithIndex());
    }

    @Override
    default ImmutableQueue> sliding(int windowSize) {
        return unitStream(stream().sliding(windowSize));
    }

    @Override
    default ImmutableQueue> sliding(int windowSize, int increment) {
        return unitStream(stream().sliding(windowSize,increment));
    }

    @Override
    default > ImmutableQueue grouped(int size, Supplier supplier) {
        return unitStream(stream().grouped(size,supplier));
    }


    @Override
    default ImmutableQueue> groupedUntil(Predicate predicate) {
        return unitStream(stream().groupedUntil(predicate));
    }

    @Override
    default ImmutableQueue> groupedUntil(BiPredicate, ? super T> predicate) {
        return unitStream(stream().groupedUntil(predicate));
    }

    default  ImmutableQueue> zipWithStream(Stream other) {
        return unitStream(stream().zipWithStream(other));
    }

    @Override
    default ImmutableQueue> groupedWhile(Predicate predicate) {
        return unitStream(stream().groupedWhile(predicate));
    }

    @Override
    default > ImmutableQueue groupedWhile(Predicate predicate, Supplier factory) {
        return unitStream(stream().groupedWhile(predicate,factory));
    }

    @Override
    default > ImmutableQueue groupedUntil(Predicate predicate, Supplier factory) {
        return unitStream(stream().groupedUntil(predicate,factory));
    }

    @Override
    default ImmutableQueue> grouped(int groupSize) {
        return unitStream(stream().grouped(groupSize));
    }



    @Override
    default ImmutableQueue distinct() {
        return unitStream(stream().distinct());
    }

    @Override
    default ImmutableQueue scanLeft(Monoid monoid) {
        return scanLeft(monoid.zero(),monoid);
    }

    @Override
    default  ImmutableQueue scanLeft(U seed, BiFunction function) {
        return unitStream(stream().scanLeft(seed,function));
    }

    @Override
    default ImmutableQueue scanRight(Monoid monoid) {
        return scanRight(monoid.zero(),monoid);
    }

    @Override
    default  ImmutableQueue scanRight(U identity, BiFunction combiner) {
        return unitStream(stream().scanRight(identity,combiner));
    }

    @Override
    default ImmutableQueue sorted() {
        return unitStream(stream().sorted());
    }

    @Override
    default ImmutableQueue sorted(Comparator c) {
        return unitStream(stream().sorted(c));
    }

    @Override
    default ImmutableQueue takeWhile(Predicate p) {
        return unitStream(stream().takeWhile(p));
    }

    @Override
    default ImmutableQueue dropWhile(Predicate p) {
        return unitStream(stream().dropWhile(p));
    }

    @Override
    default ImmutableQueue takeUntil(Predicate p) {
        return unitStream(stream().takeUntil(p));
    }

    @Override
    default ImmutableQueue dropUntil(Predicate p) {
        return unitStream(stream().dropUntil(p));
    }

    @Override
    default ImmutableQueue dropRight(int num) {
        return unitStream(stream().dropRight(num));
    }

    @Override
    default ImmutableQueue takeRight(int num) {
        return unitStream(stream().takeRight(num));
    }




    @Override
    default ImmutableQueue intersperse(T value) {
        return unitStream(stream().intersperse(value));
    }

    @Override
    default ImmutableQueue shuffle() {
        return unitStream(stream().shuffle());
    }

    @Override
    default ImmutableQueue shuffle(Random random) {
        return unitStream(stream().shuffle(random));
    }

    @Override
    default ImmutableQueue slice(long from, long to) {
        return unitStream(stream().slice(from,to));
    }

    @Override
    default > ImmutableQueue sorted(Function function) {
        return unitStream(stream().sorted(function));
    }

    @Override
    default Traversable traversable() {
        return stream();
    }

    @Override
    default ImmutableQueue prependStream(Stream stream) {
        return unitStream(stream().prependStream(stream));
    }

    @Override
    default ImmutableQueue insertAt(int pos, T... values) {
        if(pos==0)
            return prependAll(values);
        if(pos>=size())
            return appendAll(values);
        return unitStream(stream().insertAt(pos,values));
    }
    @Override
    default ImmutableQueue insertAt(int pos, T values) {
        if(pos==0)
            return prependAll(values);
        if(pos>=size())
            return append(values);
        return unitStream(stream().insertAt(pos,values));
    }

    @Override
    default ImmutableQueue appendAll(T... values) {
        ImmutableQueue res = this;
        for(T t : values){
            res = res.append(t);
        }
        return res;
    }

    @Override
    default ImmutableQueue prependAll(T... values) {
        ImmutableQueue res = this;
        for(T t : values){
            res = res.prepend(t);
        }
        return res;
    }


    @Override
    default ImmutableQueue deleteBetween(int start, int end) {
        return unitStream(stream().deleteBetween(start,end));
    }

    @Override
    default ImmutableQueue insertStreamAt(int pos, Stream stream) {
        return unitStream(stream().insertStreamAt(pos,stream));
    }



    @Override
    ImmutableQueue minus();

    @Override
    default ImmutableQueue removeAt(long pos) {
        return unitStream(stream().removeAt(pos));
    }




    @Override
    default ImmutableQueue updateAt(int pos, T value) {
        return unitStream(stream().updateAt(pos,value));
    }



    @Override
    default ImmutableQueue insertAt(int pos, Iterable values) {
        return unitIterable(IterableX.super.insertAt(pos,values));
    }
}