dev.marksman.collectionviews.ImmutableNonEmptyVector Maven / Gradle / Ivy
Show all versions of collection-views Show documentation
package dev.marksman.collectionviews;
import com.jnape.palatable.lambda.adt.Maybe;
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.Fn2;
import dev.marksman.enhancediterables.ImmutableNonEmptyFiniteIterable;
import static com.jnape.palatable.lambda.adt.Maybe.just;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static dev.marksman.collectionviews.ConcreteVectorBuilder.concreteVectorBuilder;
/**
* A {@code Vector} that is guaranteed at compile-time to be non-empty and safe from mutation anywhere.
* In other words, it owns the sole reference to the underlying collection.
*
* In addition to the guarantees of {@link Vector}, {@link NonEmptyVector}, and {@link ImmutableVector},
* provides the following benefits:
*
* - {@code ImmutableNonEmptyVector#fmap} always returns a {@code ImmutableNonEmptyVector}.
* - {@code ImmutableNonEmptyVector#reverse} always returns a {@code ImmutableNonEmptyVector}.
* - {@code ImmutableNonEmptyVector#zipWithIndex} always returns a {@code ImmutableNonEmptyVector}.
*
*
* @param the element type
*/
public interface ImmutableNonEmptyVector extends NonEmptyVector, ImmutableVector, ImmutableNonEmptyFiniteIterable {
/**
* Returns the cartesian product of this {@code ImmutableNonEmptyVector} with another {@code ImmutableNonEmptyVector}.
*
* Does not make copies of any underlying collections.
*
* The returned {@link ImmutableNonEmptyVector} will have a size of {@code size()} × {@code other.size()},
* but will allocate no extra memory (aside from a few bytes for housekeeping).
*
* @param other an {@code ImmutableNonEmptyVector} of any type
* @param the type of the other {@code ImmutableNonEmptyVector}
* @return a {@code ImmutableNonEmptyVector>}
*/
default ImmutableNonEmptyVector> cross(ImmutableNonEmptyVector other) {
return ImmutableVectors.nonEmptyCross(this, other);
}
/**
* Maps a function over this {@code ImmutableNonEmptyVector}.
*
* Returns a new {@link ImmutableNonEmptyVector} of the same size (but possibly a different type).
*
* Does not make any copies of underlying collections.
*
* This method is stack-safe, so a {@code ImmutableNonEmptyVector} can be mapped as many times as the heap permits.
*
* @param f a function from {@code A} to {@code B}.
* Not null.
* 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 of the elements contained in the output Vector.
* @return an {@code ImmutableNonEmptyVector} of the same size
*/
@Override
default ImmutableNonEmptyVector fmap(Fn1 super A, ? extends B> f) {
return ImmutableVectors.nonEmptyMap(f, this);
}
/**
* Returns the init of this {@code ImmutableNonEmptyVector}.
*
* The init of a {@link ImmutableNonEmptyVector} is the same {@code Vector} with the last element dropped.
* May be empty.
*
* Does not make copies of any underlying collections.
*
* @return an {@code ImmutableVector}
*/
@Override
default ImmutableVector init() {
return dropRight(1);
}
/**
* Returns an {@code ImmutableNonEmptyFiniteIterable} of contiguous groups of elements in this {@code ImmutableNonEmptyVector}
* that match a predicate pairwise.
*
* @param predicate the predicate function.
* This function should be referentially transparent and not perform side-effects.
* It may be called zero or more times for each element.
* @return an {@code ImmutableNonEmptyFiniteIterable>} containing the contiguous groups
*/
@Override
default ImmutableNonEmptyFiniteIterable extends ImmutableNonEmptyVector> magnetizeBy(Fn2 predicate) {
return ImmutableVectors.nonEmptyMagnetizeBy(predicate, this);
}
/**
* Creates an {@code ImmutableNonEmptyVector} with this {@code ImmutableNonEmptyVector}'s elements in reversed order.
*
* Does not make copies of any underlying collections.
*
* @return an {@code ImmutableNonEmptyVector}
*/
@Override
default ImmutableNonEmptyVector reverse() {
return ImmutableVectors.nonEmptyReverse(this);
}
/**
* Returns the tail of this {@code ImmutableNonEmptyVector}.
*
* The tail of an {@link ImmutableNonEmptyVector} is the same {@code ImmutableNonEmptyVector} with the first element dropped.
* May be empty.
*
* Does not make copies of any underlying collections.
*
* @return an {@code ImmutableVector}
*/
@Override
default ImmutableVector tail() {
return drop(1);
}
/**
* Returns an {@code ImmutableNonEmptyVector} containing the same elements as this one.
*
* Since this is an {@link ImmutableNonEmptyVector} already, this method simply returns
* itself.
*
* @return itself
*/
@Override
default ImmutableNonEmptyVector toImmutable() {
return this;
}
/**
* Attempts to convert this {@code ImmutableVector} to an {@code ImmutableNonEmptyVector}.
*
* Since this will always be successful for {@link ImmutableNonEmptyVector}s,
* this method always returns itself wrapped in a {@link Maybe#just}.
*
* Does not make copies of any underlying collections.
*
* @return this {@code ImmutableNonEmptyVector} wrapped in a {@link Maybe#just}
*/
@Override
default Maybe extends ImmutableNonEmptyVector> toNonEmpty() {
return just(this);
}
/**
* Attempts to convert this {@code ImmutableVector} to a {@code ImmutableNonEmptyVector}.
*
* Since this will always be successful for {@link ImmutableNonEmptyVector}s,
* this method always returns itself.
*
* Does not make copies of any underlying collections.
*
* @return this {@code ImmutableNonEmptyVector}
*/
@Override
default ImmutableNonEmptyVector toNonEmptyOrThrow() {
return this;
}
/**
* Zips together this {@code ImmutableNonEmptyVector} with another {@code ImmutableNonEmptyVector} by applying a zipping function.
*
* Applies the function to the successive elements of of each {@code ImmutableNonEmptyVector} until one of them runs out of elements.
*
* Does not make copies of any underlying collections.
*
* @param fn The zipping function.
* Not null.
* This function should be referentially transparent and not perform side-effects.
* It may be called zero or more times for each element.
* @param other The other {@code ImmutableNonEmptyVector}
* @param The element type of the other {@code ImmutableNonEmptyVector}
* @param The element type of the result
* @return A {@code ImmutableNonEmptyVector}
*/
default ImmutableNonEmptyVector zipWith(Fn2 fn, ImmutableNonEmptyVector other) {
return ImmutableVectors.nonEmptyZipWith(fn, this, other);
}
/**
* Zips this {@code ImmutableNonEmptyVector} with its indices.
*
* Does not make copies of any underlying collections.
*
* @return a new {@code ImmutableNonEmptyVector} containing pairs consisting of all elements of this {@code ImmutableNonEmptyVector} paired with their index.
* Indices start at 0.
*/
@Override
default ImmutableNonEmptyVector> zipWithIndex() {
return ImmutableVectors.nonEmptyZipWithIndex(this);
}
/**
* Creates a {@code ImmutableNonEmptyVector} with the given elements.
*
* @param first the first element
* @param more the remaining elements
* @param the element type
* @return an {@code ImmutableNonEmptyVector}
*/
@SuppressWarnings("varargs")
@SafeVarargs
static ImmutableNonEmptyVector of(A first, A... more) {
return Vectors.nonEmptyVectorOf(first, more);
}
/**
* Creates a new {@code NonEmptyVectorBuilder}.
*
* @param first the first element
* @param the element type
* @return an empty {@link VectorBuilder}
*/
static NonEmptyVectorBuilder builder(A first) {
return concreteVectorBuilder(nothing(), first);
}
/**
* Creates a new {@code NonEmptyVectorBuilder} with an initial capacity hint.
*
* @param initialCapacity an initial capacity hint.
* Must be >= 0.
* @param first the first element
* @param the element type
* @return an empty {@link VectorBuilder}
*/
static NonEmptyVectorBuilder builder(int initialCapacity, A first) {
return concreteVectorBuilder(just(initialCapacity), first);
}
}