package lv.enes.mc.eris_alchemy.utils; import jakarta.annotation.Nonnull; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Stream; public sealed abstract class ConsList { public static ConsList cons(E car, ConsList cdr) { return new Cons<>(car, cdr); } public static ConsList nil() { return Nil.of(); } @Nonnull public abstract Optional car(); @Nonnull public abstract ConsList cdr(); public boolean contains(E elem) { return stream().anyMatch(x -> Objects.equals(x, elem)); } public Stream stream() { var car = car(); if (car.isEmpty()) { return Stream.empty(); } return Stream.>>of( () -> Stream.of(car.get()), () -> cdr().stream() ) .flatMap(Supplier::get); } @Override public String toString() { if (car().isEmpty()) { return "[]"; } var sb = new StringBuilder("["); sb.append(car().get()); stream().skip(1) .forEach(x -> { sb.append(" -> "); sb.append(x); }); sb.append("]"); return sb.toString(); } private static final class Cons extends ConsList { private final E car; private final ConsList cdr; public Cons(E car, ConsList cdr) { this.car = car; this.cdr = cdr; } @Nonnull @Override public Optional car() { return Optional.of(car); } @Nonnull @Override public ConsList cdr() { return cdr; } } private static final class Nil extends ConsList { private static final Nil INSTANCE = new Nil<>(); @SuppressWarnings("unchecked") public static Nil of() { return (Nil)INSTANCE; } private Nil(){} @Nonnull @Override public Optional car() { return Optional.empty(); } @Nonnull @Override public ConsList cdr() { return Nil.of(); } } }