package xapi.fu; import java.io.Serializable; import java.util.function.Consumer; /** * @author James X. Nelson (james@wetheinter.net) * Created on 07/11/15. */ @FunctionalInterface @SuppressWarnings("unchecked") // yes, this api will let you do terrible things. Don't do terrible things. public interface In1<I> extends HasInput, Rethrowable, Lambda { void in(I in); @Override default int accept(int position, Object... values) { in((I) values[position++]); return position; } default Consumer<I> toConsumer() { return this::in; } default Do provide(I in) { return ()->in(in); } default Do provide(Out1<I> in) { return ()->in(in.out1()); } default <N> In2<N, I> requireBefore(In1<N> and) { return In2.in2(and, this); } default <N> In2<I, N> requireAfter(In1<N> and) { return In2.in2(this, and); } static <I> In1<I> in1(Consumer<I> of) { return of::accept; } /** * This method just exists to give you somewhere to create a lambda that will rethrow exceptions, * but exposes an exceptionless api. If you don't have to call code with checked exceptions, * prefer the standard {@link #in1(Consumer)}, as try/catch can disable / weaken some JIT compilers. */ static <I> In1<I> in1Unsafe(In1Unsafe<I> of) { return of; } static <I> In1<I> noop() { return ignored->{}; } interface In1Unsafe <I> extends In1<I> { void inUnsafe(I in) throws Throwable; default void in(I in) { try { inUnsafe(in); } catch (Throwable e) { throw rethrow(e); } } } static <I1, I2> In1<I1> from2(In2<I1, I2> adapt, I2 i2) { return i1 -> adapt.in(i1, i2); } static <I1, I2> In1<I1> mapped1(In2<I1, I2> adapt, In1Out1<I1, I2> mapper) { return i1 -> adapt.in(i1, mapper.io(i1)); } static <I1, I2> In1<I1> mapped1Reverse(In1Out1<I1, I2> mapper, In2<I1, I2> operation) { return i1 -> { final I2 mapped = mapper.io(i1); operation.in(i1, mapped); }; } static <I1, I2> In1<I2> mapped2(In2<I1, I2> adapt, In1Out1<I2, I1> i1) { return i2 -> adapt.in(i1.io(i2), i2); } static <I1, I2> In1<I2> mapped2Reverse(In1Out1<I2, I1> mapper, In2<I1, I2> adapt) { return i2 -> { final I1 mapped = mapper.io(i2); adapt.in(mapped, i2); }; } static <I1, I2> In1<I2> from1(In2<I1, I2> adapt, I1 i1) { return i2 -> adapt.in(i1, i2); } static <I1> In1<In1<I1>> receiver(I1 value) { // We need to declare a variable with this type for type inferment to work. final In2<In1<I1>, I1> in2 = In1::in; return in2.provide2(value); } static <I> In1<I> ignored(Runnable r) { return ignored -> r.run(); } default void forEach(Iterable<I> value) { value.forEach(toConsumer()); } default <To> In1<To> map1(In1Out1<To, I> mapper) { return i1->in(mapper.io(i1)); } static <E> In1Serializable<E> serializable1(In1<E> from) { return from::in; } interface In1Serializable <I> extends In1<I>, Serializable { } default <V> In2<I, V> ignore2() { return (i, ignored) -> in(i); } default <V> In2<V, I> ignore1() { return (ignored, i) -> in(i); } }