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

de.scravy.bedrock.hlist.C Maven / Gradle / Ivy

The newest version!
package de.scravy.bedrock.hlist;

import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.Value;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

@Value
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@EqualsAndHashCode(callSuper = false)
public class C> extends HList> {

  private final E head;
  private final L tail;

  @Override
  public int size() {
    return 1 + tail.size();
  }

  @Override
  public  T foldl(@Nonnull final BiFunction f, final T init) {
    return tail.foldl(f, f.apply(init, head));
  }

  @Override
  public  T foldr(@Nonnull final BiFunction f, final T init) {
    return f.apply(head, tail.foldr(f, init));
  }

  @Override
  C mask(@Nonnegative final int index, @Nonnull final ForEachWithIndexPredicate predicate) {
    final C thiz = predicate.test(index, head) ? this : withHead(null);
    return thiz.withTail(tail.mask(index + 1, predicate));
  }

  @Nonnull
  @Override
  public Iterator iterator() {
    return new Iterator() {
      HList current = C.this;

      @Override
      public boolean hasNext() {
        return current != Nil.INSTANCE;
      }

      @Override
      public Object next() {
        final C xs = (C) current;
        current = xs.tail;
        return xs.head;
      }
    };
  }

  @Nonnull
  public  C> cons(final F elem) {
    return new C<>(elem, this);
  }

  @Nonnull
  public  C withHead(final F head) {
    if (head == this.head) {
      @SuppressWarnings("unchecked") final C thiz = (C) this;
      return thiz;
    }
    return new C<>(head, tail);
  }

  @Nonnull
  public > C withTail(final M tail) {
    if (tail == this.tail) {
      @SuppressWarnings("unchecked") final C thiz = (C) this;
      return thiz;
    }
    return new C<>(head, tail);
  }

  @Override
  public String toString() {
    return stream()
      .map(Objects::toString)
      .collect(Collectors.joining(",", "[", "]"));
  }

  @Override
  public int compareTo(@Nonnull final C that) {
    final int headComparison = Objects.compare(getHead(), that.getHead(), Comparator.nullsFirst((l, r) -> {
      @SuppressWarnings("unchecked") final int result = ((Comparable) l).compareTo(r);
      return result;
    }));
    if (headComparison != 0) {
      return headComparison;
    }
    return getTail().compareTo(that.getTail());
  }
}