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

dev.marksman.enhancediterables.ImmutableNonEmptyFiniteIterable Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package dev.marksman.enhancediterables;

import com.jnape.palatable.lambda.adt.hlist.Tuple2;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.Fn2;
import com.jnape.palatable.lambda.functions.builtin.fn1.Init;
import com.jnape.palatable.lambda.functions.builtin.fn1.Reverse;
import com.jnape.palatable.lambda.functions.builtin.fn2.CartesianProduct;
import com.jnape.palatable.lambda.functions.builtin.fn2.Intersperse;
import com.jnape.palatable.lambda.functions.builtin.fn2.Map;
import com.jnape.palatable.lambda.functions.builtin.fn2.PrependAll;
import com.jnape.palatable.lambda.functions.builtin.fn3.ZipWith;
import com.jnape.palatable.lambda.monoid.builtin.Concat;

import static dev.marksman.enhancediterables.EnhancedIterables.immutableFiniteIterable;
import static dev.marksman.enhancediterables.EnhancedIterables.immutableNonEmptyFiniteIterableOrThrow;
import static java.util.Objects.requireNonNull;

/**
 * An {@code EnhancedIterable} that is finite, safe from mutation, and guaranteed to contain at least one element.
 *
 * @param  the element type
 */
public interface ImmutableNonEmptyFiniteIterable extends ImmutableFiniteIterable, ImmutableNonEmptyIterable,
        NonEmptyFiniteIterable {

    @Override
    ImmutableFiniteIterable tail();

    /**
     * Lazily concatenates another {@code ImmutableFiniteIterable} to the end of this {@code ImmutableNonEmptyFiniteIterable},
     * yielding a new {@code ImmutableIterable}.
     *
     * @param other the other {@link ImmutableIterable}
     * @return an {@code ImmutableIterable}
     */
    @Override
    default ImmutableNonEmptyFiniteIterable concat(ImmutableFiniteIterable other) {
        requireNonNull(other);
        return immutableNonEmptyFiniteIterableOrThrow(Concat.concat(this, other));
    }

    /**
     * Returns the lazily computed cartesian product of this {@code ImmutableNonEmptyFiniteIterable} with another {@code ImmutableNonEmptyFiniteIterable}.
     *
     * @param other an {@code ImmutableNonEmptyFiniteIterable} of any type
     * @param    the type of the other {@code ImmutableNonEmptyFiniteIterable}
     * @return a {@code ImmutableNonEmptyFiniteIterable>}
     */
    default  ImmutableNonEmptyFiniteIterable> cross(ImmutableNonEmptyFiniteIterable other) {
        requireNonNull(other);
        return immutableNonEmptyFiniteIterableOrThrow(CartesianProduct.cartesianProduct(this, other));
    }

    /**
     * Returns a new {@code ImmutableNonEmptyFiniteIterable} by applying a function to all elements of this {@code ImmutableNonEmptyFiniteIterable}.
     *
     * @param f   a function from {@code A} to {@code B}.
     *            This function should be referentially transparent and not perform side-effects.
     *            It may be called zero or more times for each element.
     * @param  the type returned by {@code f}
     * @return an ImmutableNonEmptyFiniteIterable<B>
     */
    @Override
    default  ImmutableNonEmptyFiniteIterable fmap(Fn1 f) {
        requireNonNull(f);
        return immutableNonEmptyFiniteIterableOrThrow(Map.map(f, this));
    }

    @Override
    default ImmutableFiniteIterable init() {
        return immutableFiniteIterable(Init.init(this));
    }

    /**
     * Returns a new {@code ImmutableNonEmptyFiniteIterable} with the provided separator value injected between each value of this
     * {@code ImmutableNonEmptyFiniteIterable}.
     * 

* If this {@code ImmutableNonEmptyFiniteIterable} contains only one element, it is left untouched. * * @param separator the separator value * @return an ImmutableNonEmptyFiniteIterable<A> */ @Override default ImmutableNonEmptyFiniteIterable intersperse(A separator) { return immutableNonEmptyFiniteIterableOrThrow(Intersperse.intersperse(separator, this)); } /** * Lazily prepends an element to the front of this {@code ImmutableNonEmptyFiniteIterable}, yielding a new {@code ImmutableNonEmptyFiniteIterable}. * * @param element the element to prepend * @return a ImmutableNonEmptyFiniteIterable<A> */ @Override default ImmutableNonEmptyFiniteIterable prepend(A element) { return immutableNonEmptyFiniteIterable(element, this); } /** * Returns a new {@code ImmutableNonEmptyFiniteIterable} with the provided separator value injected before each value of this * {@code ImmutableNonEmptyFiniteIterable}. * * @param separator the separator value * @return an ImmutableNonEmptyFiniteIterable<A> */ @Override default ImmutableNonEmptyFiniteIterable prependAll(A separator) { return immutableNonEmptyFiniteIterableOrThrow(PrependAll.prependAll(separator, this)); } @Override default ImmutableNonEmptyFiniteIterable reverse() { return immutableNonEmptyFiniteIterableOrThrow(Reverse.reverse(this)); } default ImmutableNonEmptyFiniteIterable zipWith(Fn2 fn, ImmutableNonEmptyIterable other) { requireNonNull(fn); requireNonNull(other); return immutableNonEmptyFiniteIterableOrThrow(ZipWith.zipWith(fn, this, other)); } static ImmutableNonEmptyFiniteIterable immutableNonEmptyFiniteIterable(A head, ImmutableFiniteIterable tail) { requireNonNull(tail); return new ImmutableNonEmptyFiniteIterable() { @Override public A head() { return head; } @Override public ImmutableFiniteIterable tail() { return tail; } }; } @SafeVarargs static ImmutableNonEmptyFiniteIterable of(A first, A... more) { return EnhancedIterables.of(first, more); } }