com.shapesecurity.functional.data.NonEmptyImmutableList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shift Show documentation
Show all versions of shift Show documentation
Shift format ECMAScript 6 AST tooling
/*
* Copyright 2014 Shape Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.shapesecurity.functional.data;
import com.shapesecurity.functional.F;
import com.shapesecurity.functional.F2;
import com.shapesecurity.functional.Pair;
import org.jetbrains.annotations.NotNull;
public final class NonEmptyImmutableList extends ImmutableList {
@NotNull
public final T head;
@NotNull
public final ImmutableList tail;
protected NonEmptyImmutableList(@NotNull T head, @NotNull final ImmutableList tail) {
super(tail.length + 1);
this.head = head;
this.tail = tail;
}
@NotNull
public ImmutableList tail() {
return tail;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NonEmptyImmutableList)) {
return false;
}
NonEmptyImmutableList list = (NonEmptyImmutableList) o;
return this.head.equals(list.head) && this.tail().equals(list.tail());
}
@NotNull
@Override
public A foldLeft(@NotNull F2 f, @NotNull A init) {
ImmutableList list = this;
while (list instanceof NonEmptyImmutableList) {
init = f.apply(init, ((NonEmptyImmutableList) list).head);
list = ((NonEmptyImmutableList) list).tail();
}
return init;
}
@NotNull
@Override
public A foldRight(@NotNull F2 super T, A, A> f, @NotNull A init) {
return f.apply(this.head, this.tail().foldRight(f, init));
}
@NotNull
@Override
public Maybe maybeHead() {
return Maybe.just(this.head);
}
@NotNull
@Override
public Maybe maybeLast() {
if (this.tail().isEmpty()) {
return Maybe.just(this.head);
}
return this.tail().maybeLast();
}
@NotNull
@Override
public Maybe> maybeTail() {
return Maybe.just(this.tail());
}
@NotNull
@Override
public Maybe> maybeInit() {
if (this.tail().isEmpty()) {
return Maybe.just(nil());
}
return this.tail().maybeInit().map(t -> t.cons(this.head));
}
@NotNull
public final T last() {
NonEmptyImmutableList nel = this;
while (true) {
if (nel.tail().isEmpty()) {
return nel.head;
}
nel = (NonEmptyImmutableList) nel.tail();
}
}
@NotNull
public final ImmutableList init() {
if (this.tail().isEmpty()) {
return nil();
}
return cons(this.head, ((NonEmptyImmutableList) this.tail()).init());
}
@NotNull
@Override
public ImmutableList filter(@NotNull F f) {
return f.apply(this.head) ? cons(this.head, this.tail().filter(f)) : this.tail().filter(f);
}
@NotNull
@Override
public NonEmptyImmutableList map(@NotNull F f) {
return ImmutableList.cons(f.apply(this.head), this.tail().map(f));
}
@Override
@NotNull
public final NonEmptyImmutableList mapWithIndex(@NotNull F2 f) {
int length = this.length;
@SuppressWarnings("unchecked")
B[] result = (B[]) new Object[length];
ImmutableList list = this;
for (int i = 0; i < length; i++) {
result[i] = f.apply(i, ((NonEmptyImmutableList) list).head);
list = ((NonEmptyImmutableList) list).tail();
}
ImmutableList nList = nil();
for (int i = length - 1; i >= 0; i--) {
nList = nList.cons(result[i]);
}
return (NonEmptyImmutableList) nList;
}
@NotNull
@Override
public ImmutableList take(int n) {
if (n <= 0) {
return nil();
}
return cons(this.head, this.tail().take(n - 1));
}
@NotNull
@Override
public ImmutableList drop(int n) {
if (n <= 0) {
return this;
}
return this.tail().drop(n - 1);
}
@NotNull
@Override
public Maybe> toNonEmptyList() {
return Maybe.just(this);
}
@NotNull
@Override
public Maybe decons(@NotNull F2, B> f) {
return Maybe.just(f.apply(this.head, this.tail()));
}
@NotNull
@Override
public ImmutableList zipWith(@NotNull F2 f, @NotNull ImmutableList list) {
if (list instanceof NonEmptyImmutableList) {
NonEmptyImmutableList nonEmptyList = (NonEmptyImmutableList) list;
return ImmutableList.cons(f.apply(this.head, nonEmptyList.head), this.tail().zipWith(f, nonEmptyList.tail()));
}
return nil();
}
@Override
public boolean isEmpty() {
return false;
}
@NotNull
@Override
public ImmutableList append(@NotNull ImmutableList defaultClause) {
return cons(this.head, this.tail().append(defaultClause));
}
@Override
public boolean exists(@NotNull F f) {
return f.apply(this.head) || this.tail().exists(f);
}
@NotNull
@Override
public Pair, ImmutableList> span(@NotNull F f) {
if (!f.apply(this.head)) {
return new Pair<>(nil(), this);
}
Pair, ImmutableList> s = this.tail().span(f);
return new Pair<>(s.a.cons(this.head), s.b);
}
@NotNull
@Override
public ImmutableList flatMap(@NotNull F> f) {
return f.apply(this.head).append(this.tail().flatMap(f));
}
@NotNull
@Override
public ImmutableList removeAll(@NotNull F f) {
if (f.apply(this.head)) {
return this.tail().removeAll(f);
}
return cons(this.head, this.tail().removeAll(f));
}
@NotNull
@Override
public NonEmptyImmutableList reverse() {
return this.reverse(nil());
}
@NotNull
@Override
public Pair> mapAccumL(@NotNull F2> f, @NotNull B acc) {
Pair pair = f.apply(acc, this.head);
Pair> bListPair = this.tail().mapAccumL(f, pair.a);
return new Pair<>(bListPair.a, ImmutableList.cons(pair.b, bListPair.b));
}
@NotNull
private NonEmptyImmutableList reverse(@NotNull ImmutableList acc) {
if (this.tail().isEmpty()) {
return acc.cons(this.head);
}
return ((NonEmptyImmutableList) this.tail()).reverse(cons(this.head, acc));
}
@Override
protected int calcHashCode() {
int start = HashCodeBuilder.init();
start = HashCodeBuilder.put(start, "List");
start = HashCodeBuilder.put(start, head);
return HashCodeBuilder.put(start, tail);
}
}