@FunctionalInterface
public interface Function3<X0, X1, X2, Y> {

    Y apply(X0 x0, X1 x1, X2 x2);

    default <Z> Function3<X0, X1, X2, Z> andThen(final Function<? super Y, ? extends Z> after) {
        Objects.requireNonNull(after);
        return (x0, x2, x3) -> after.apply(this.apply(x0, x2, x3));
    }
} public class SFunc<X, R>
    implements Serializable, Function<X, R>, SLambda<SFunc<X, R>> {

    private static final long serialVersionUID = -8241959687855651918L;

    private final BiFunction<? super Function<X, R>, ? super X, ? extends R> body;

    /**
     * constructor
     *
     * @param body function body
     */
    public SFunc(final BiFunction<? super Function<X, R>, ? super X, ? extends R> body) {
        this.body = Objects.requireNonNull(body);
    }

    @Override
    public R apply(final X x) {
        return this.body.apply(this, x);
    }

    /**
     * bind parameter to this function.
     *
     * @param x argument to bind
     * @return curried function
     */
    public SSuppl<R> bind(final X x) {
        return this.bind(() -> x);
    }

    /**
     * bind parameter to this function.
     *
     * @param x argument to bind
     * @return curried function
     */
    public SSuppl<R> bind(final Supplier<? extends X> x) {
        return new SSuppl<>(self -> this.apply(x.get()));
    }

    /**
     * return function body.
     *
     * @return function body
     */
    public BiFunction<? super Function<X, R>, ? super X, ? extends R> body() {
        return this.body;
    }

    @Override
    public SFunc<X, R> memoize() {
        return new SFunc<>(Functional.memoize(this.body));
    }

    @Override
    public String toString() {
        return this.body.toString();
    }

    @Override
    public int hashCode() {
        return this.body.hashCode();
    }

    @Override
    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        } else if (this == o) {
            return true;
        } else if (!(o instanceof SFunc)) {
            return false;
        }

        final SFunc<?, ?> that = (SFunc<?, ?>) o;
        return this.body.equals(that.body);
    }
} public class SFunc3<X0, X1, X2, Y>
    implements Serializable, Function3<X0, X1, X2, Y>, SLambda<SFunc3<X0, X1, X2, Y>> {

    private static final long serialVersionUID = 5099015871546179565L;

    private final Function4<? super Function3<X0, X1, X2, Y>, ? super X0, ? super X1, ? super X2, ? extends Y> body;

    /**
     * constructor
     *
     * @param body function body
     */
    public SFunc3(
        final Function4<? super Function3<X0, X1, X2, Y>, ? super X0, ? super X1, ? super X2, ? extends Y> body) {
        this.body = Objects.requireNonNull(body);
    }

    @Override
    public Y apply(final X0 x0, final X1 x1, final X2 x2) {
        return this.body.apply(this, x0, x1, x2);
    }

    /**
     * bind parameter to this function.
     *
     * @param x0 argument to bind
     * @return curried function
     */
    public SFunc2<X1, X2, Y> bind(final X0 x0) {
        return this.bind(() -> x0);
    }

    /**
     * bind parameter to this function.
     *
     * @param x0 argument to bind
     * @return curried function
     */
    public SFunc2<X1, X2, Y> bind(final Supplier<? extends X0> x0) {
        return new SFunc2<>((self, y, z) -> this.apply(x0.get(), y, z));
    }

    /**
     * bind parameter to this function.
     *
     * @param x0 1st argument to bind
     * @param x1 2nd argument to bind
     * @return curried function
     */
    public SFunc<X2, Y> bind(final X0 x0, final X1 x1) {
        return this.bind(() -> x0, () -> x1);
    }

    /**
     * bind parameter to this function.
     *
     * @param x0 1st argument to bind
     * @param x1 2nd argument to bind
     * @return curried function
     */
    public SFunc<X2, Y> bind(final Supplier<? extends X0> x0, final Supplier<? extends X1> x1) {
        return this.bind(x0).bind(x1);
    }

    /**
     * bind parameter to this function.
     *
     * @param x 1st argument to bind
     * @param y 2nd argument to bind
     * @param z 3rd argument to bind
     * @return curried function
     */
    public SSuppl<Y> bind(final X0 x, final X1 y, final X2 z) {
        return this.bind(() -> x, () -> y, () -> z);
    }

    /**
     * bind parameter to this function.
     *
     * @param x0 1st argument to bind
     * @param x1 2nd argument to bind
     * @param x2 3rd argument to bind
     * @return curried function
     */
    public SSuppl<Y> bind(final Supplier<? extends X0> x0, final Supplier<? extends X1> x1,
        final Supplier<? extends X2> x2) {
        return this.bind(x0).bind(x1).bind(x2);
    }

    /**
     * return function body.
     *
     * @return function body
     */
    public Function4<? super Function3<X0, X1, X2, Y>, ? super X0, ? super X1, ? super X2, ? extends Y> body() {
        return this.body;
    }

    @Override
    public SFunc3<X0, X1, X2, Y> memoize() {
        return new SFunc3<>(Functional.memoize(this.body));
    }

    @Override
    public String toString() {
        return this.body.toString();
    }

    @Override
    public int hashCode() {
        return this.body.hashCode();
    }

    @Override
    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        } else if (this == o) {
            return true;
        } else if (!(o instanceof SFunc3)) {
            return false;
        }

        final SFunc3<?, ?, ?, ?> that = (SFunc3<?, ?, ?, ?>) o;
        return this.body.equals(that.body);
    }
} public class $3<T1, T2, T3>
    implements Serializable, Consumer3<T1, T2, T3>, Supplier<$3<T1, T2, T3>>, Consumer<$3<T1, T2, T3>> {

    private static final long serialVersionUID = 1387913510813532191L;

    /** first element */
    @SuppressWarnings("PublicField")
    public T1 _1; // NOPMD

    /** second element */
    @SuppressWarnings("PublicField")
    public T2 _2; // NOPMD

    /** third element */
    @SuppressWarnings("PublicField")
    public T3 _3; // NOPMD

    @Destructive
    @Override
    public void accept(final $3<T1, T2, T3> that) {
        this._1 = that._1;
        this._2 = that._2;
        this._3 = that._3;
    }

    /**
     * set elements then return {@code this} instance.
     *
     * @param that the element supplier
     * @return {@code this} instance
     */
    @Destructive
    public $3<T1, T2, T3> set(final $3<? extends T1, ? extends T2, ? extends T3> that) {
        return (that == null) ? this.set(null, null, null) : this.set(that._1, that._2, that._3);
    }

    /**
     * set elements then return {@code this} instance.
     *
     * @param _1 first element
     * @param _2 second element
     * @param _3 third element
     * @return {@code this} instance
     */
    @Destructive
    public $3<T1, T2, T3> set(final T1 _1, final T2 _2, final T3 _3) {
        this.accept(_1, _2, _3);
        return this;
    }

    @Override
    public $3<T1, T2, T3> get() { return this;}

    @Destructive
    @Override
    public void accept(final T1 _1, final T2 _2, final T3 _3) {
        this._1 = _1;
        this._2 = _2;
        this._3 = _3;
    }

    /**
     * get 1st element
     *
     * @return 1st element
     */
    public T1 _1() { return this._1; }

    /**
     * set 1st element
     *
     * @param _1 1st element
     * @return {@code this}
     */
    @Destructive
    public $3<T1, T2, T3> _1(final T1 _1) {
        this._1 = _1;
        return this;
    }

    /**
     * get 2nd element
     *
     * @return 2nd element
     */
    public T2 _2() { return this._2; }

    /**
     * set 2nd element
     *
     * @param _2 2st element
     * @return {@code this}
     */
    @Destructive
    public $3<T1, T2, T3> _2(final T2 _2) {
        this._2 = _2;
        return this;
    }

    /**
     * get 3rt element
     *
     * @return 1st element
     */
    public T3 _3() { return this._3; }

    /**
     * set 3rd element
     *
     * @param _3 3rd element
     * @return {@code this}
     */
    @Destructive
    public $3<T1, T2, T3> _3(final T3 _3) {
        this._3 = _3;
        return this;
    }

    /**
     * expand to all combination of two element tuples.
     *
     * @return all combination of two element tuples
     */
    public $3<$2<T1, T2>, $2<T2, T3>, $2<T1, T3>> _12_23_13() { return tuple(this._12(), this._23(), this._13()); }

    /**
     * get duo of first and second element.
     *
     * @return duo of first and second element
     */
    public $2<T1, T2> _12() { return tuple(this._1, this._2); }

    /**
     * get duo of second and third element.
     *
     * @return duo of second and third element
     */
    public $2<T2, T3> _23() { return tuple(this._2, this._3); }

    /**
     * get duo of first and third element.
     *
     * @return duo of first and third element
     */
    public $2<T1, T3> _13() { return tuple(this._1, this._3); }

    /**
     * set first and second element the return {@code this} instance.
     *
     * @param t first and second element
     * @return {@code this} instance
     */
    @Destructive
    public $3<T1, T2, T3> _12(final $2<T1, T2> t) {
        this._1 = t._1;
        this._2 = t._2;
        return this;
    }

    /**
     * set second and third element the return {@code this} instance.
     *
     * @param t second and third element
     * @return {@code this} instance
     */
    @Destructive
    public $3<T1, T2, T3> _23(final $2<T2, T3> t) {
        this._2 = t._1;
        this._3 = t._2;
        return this;
    }

    /**
     * set first and third element the return {@code this} instance.
     *
     * @param t first and third element
     * @return {@code this} instance
     */
    @Destructive
    public $3<T1, T2, T3> _13(final $2<T1, T3> t) {
        this._1 = t._1;
        this._3 = t._2;
        return this;
    }

    /**
     * create order reversed tuple.
     *
     * @return newly constructed reversed tuple
     */
    public $3<T3, T2, T1> _321() { return tuple(this._3, this._2, this._1); }

    /**
     * rotate this tuple.
     *
     * @return rotated tuple
     */
    public $3<T3, T1, T2> _312() { return tuple(this._3, this._1, this._2); }

    @Override
    public int hashCode() { return Objects.hash(this.getClass(), this._1, this._2, this._3); }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof $3)) return false;

        final $3<?, ?, ?> that = cast(o);

        return equiv(this._1, that._1) && equiv(this._2, that._2) && equiv(this._3, that._3);
    }

    @Override
    public String toString() { return String.format("(%s, %s, %s)", this._1, this._2, this._3); }
} @SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
public class $int
    extends AbstractRef<Integer, $int>
    implements NumberRef<Integer, $int>, Comparable<$int>, IntSupplier, IntConsumer {

    private static final long serialVersionUID = -5827553121494604722L;

    /** the value. */
    @SuppressWarnings("PublicField")
    public int $; // NOPMD

    /**
     * constructor.
     */
    protected $int() { this(0); }

    /**
     * constructor.
     *
     * @param $ the value.
     */
    protected $int(final int $) { this.$ = $; }

    @Override
    public void accept(final Integer $) { this.$ = $; }

    /**
     * set value then return this instance.
     *
     * @param $ value
     * @return {@code this}
     */
    public $int set(final int $) {
        this.$ = $;
        return this;
    }

    @Override
    public Integer get() { return this.$; }

    @Override
    public int getAsInt() { return this.$; }

    @Override
    public void accept(final int $) { this.$ = $; }

    @Override
    public int compareTo(final $int that) { return this.compareTo(that.$); }

    public int compareTo(final int that) { return Integer.compare(this.$, that); }

    @Override
    public $int add(final Integer $) {
        this.$ += $;
        return this;
    }

    @Override
    public $int mul(final Integer $) {
        this.$ *= $;
        return this;
    }

    @Override
    public $int div(final Integer $) {
        this.$ /= $;
        return this;
    }

    @Override
    public $int negate() {
        this.$ = -this.$;
        return this;
    }
} public class Expressive {

    /** non private for subtyping. */
    protected Expressive() { }

    public static class RaisedException
        extends RuntimeException {

        private static final long serialVersionUID = 1037309592665638717L;

        public RaisedException(final Throwable e) { super(e); }
    }

    /**
     * Throw exception in expression manner.
     *
     * @param <T> the type of expression
     * @param e exception
     * @return actually return nothing
     */
    public static <T> T raise(final Throwable e) { return raise(() -> e); }

    /**
     * Throw exception in expression manner.
     *
     * @param <T> the type of expression
     * @param f supplies exception to throw
     * @return actually return nothing
     */
    public static <T> T raise(final Supplier<? extends Throwable> f) {

        throw opt(f.get()).map(e -> {
            if (e instanceof Error er) throw er;
            if (e instanceof RuntimeException re) return re;
            return new RaisedException(e);
        }).or(() -> new NullPointerException("supplier returns null: " + f));
    }

    /**
     * Block statement.
     *
     * @param stmt statement body
     */
    public static void let(final Statement stmt) { stmt.run(); }

    /**
     * Block statement.
     *
     * @param <E> the type of exception
     * @param stmt statement body
     */
    public static <E extends Exception> void letTry(final RunnableE<E> stmt) throws E { stmt.run(); }

    /**
     * In-line evaluation expression.
     *
     * @param <R> the type of expression
     * @param <E> the type of exception
     * @param expr expression body
     * @return the value of body expression
     */
    public static <R, E extends Exception> R evalTry(final SupplierE<R, E> expr) throws E { return expr.get(); }

    /**
     * In-line evaluation expression.
     *
     * @param <R> the type of expression
     * @param expr expression body
     * @return the value of body expression
     */
    public static <R> R eval(final Expression<R> expr) { return expr.get(); }

    /**
     * Block statement.
     *
     * @param value the value
     * @param stmt expression body
     */
    public static <T> void let(final T value, final Consumer<? super T> stmt) { stmt.accept(value); }

    /**
     * Block statement.
     *
     * @param <E> the type of exception
     * @param value the value
     * @param stmt expression body
     */
    public static <T, E extends Exception> void letTry(final T value, final ConsumerE<? super T, E> stmt) throws E {
        stmt.accept(value);
    }

    /**
     * Block statement which applied only if the value is an instance of the statement's argument type.
     *
     * @param value the value
     * @param stmt statement body
     */
    public static <T> void ifInstance(final Object value, final Consumer<T> stmt) {
        if (argTypeOf(stmt).isInstance(value)) stmt.accept(cast(value));
    }

    /**
     * if-else statement alternative.
     *
     * @param <T> context type
     * @param context context value
     * @param cond context test function
     * @param then context conversion function used if the condition is {@code true}
     * @param other context conversion function used if the condition is {@code false}
     */
    public static <T> void let(final T context, final Predicate<? super T> cond, final Consumer<? super T> then,
        final Consumer<? super T> other) {

        if (cond.test(context)) //
            then.accept(context);
        else //
            other.accept(context);
    }

    /**
     * In-line evaluation expression.
     *
     * @param <T> value type
     * @param <R> the type of expression
     * @param val the value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T, R> R eval(final T val, final Function<? super T, ? extends R> expr) { return expr.apply(val); }

    /**
     * In-line evaluation expression.
     *
     * @param <T> value type
     * @param <R> the type of expression
     * @param <E> the type of exception
     * @param val the value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T, R, E extends Exception> R evalTry(final T val, final FunctionE<? super T, ? extends R, E> expr)
        throws E { return expr.apply(val); }

    /**
     * In-line evaluation expression.
     *
     * @param <T1> first value type
     * @param <T2> second value type
     * @param <R> the type of expression
     * @param val1 first value
     * @param val2 second value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T1, T2, R> R eval(final T1 val1, final T2 val2,
        final BiFunction<? super T1, ? super T2, ? extends R> expr) { return expr.apply(val1, val2); }

    /**
     * In-line evaluation expression.
     *
     * @param <T1> first value type
     * @param <T2> second value type
     * @param <R> the type of expression
     * @param <E> the type of exception
     * @param val1 first value
     * @param val2 second value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T1, T2, R, E extends Exception> R evalTry(final T1 val1, final T2 val2,
        final Function2E<? super T1, ? super T2, ? extends R, E> expr) throws E { return expr.apply(val1, val2); }

    /**
     * In-line evaluation expression.
     *
     * @param <T1> first value type
     * @param <T2> second value type
     * @param <T3> third value type
     * @param <R> the type of expression
     * @param val1 first value
     * @param val2 second value
     * @param val3 third value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T1, T2, T3, R> R eval(final T1 val1, final T2 val2, final T3 val3,
        final Function3<? super T1, ? super T2, ? super T3, ? extends R> expr) { return expr.apply(val1, val2, val3); }

    /**
     * In-line evaluation expression.
     *
     * @param <T1> first value type
     * @param <T2> second value type
     * @param <T3> third value type
     * @param <R> the type of expression
     * @param <E> the type of exception
     * @param val1 first value
     * @param val2 second value
     * @param val3 third value
     * @param expr expression body
     * @return the value function returned
     */
    public static <T1, T2, T3, R, E extends Exception> R evalTry(final T1 val1, final T2 val2, final T3 val3,
        final Function3E<? super T1, ? super T2, ? super T3, ? extends R, E> expr) throws E {
        return expr.apply(val1, val2, val3);
    }

    /**
     * evaluate following forms then return evaluation result of first expressions.
     *
     * @param <T> the type of expression
     * @param first evaluation result of this expression
     * @param forms evaluation target forms. argument is evaluation result of {@code first}.
     * @return first expression evaluation result
     */
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    @SafeVarargs
    public static <T> T prog1(final Supplier<? extends T> first, final Consumer<? super T>... forms) {

        final var val = first.get();

        list(forms).each(f -> f.accept(val));

        return val;
    }

    /**
     * evaluate following forms then return evaluation result of first expressions.
     *
     * @param <T> the type of expression
     * @param <E> the type of exception
     * @param first evaluation result of this expression
     * @param forms evaluation target forms. argument is evaluation result of {@code first}.
     * @return first expression evaluation result
     */
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    @SafeVarargs
    public static <T, E extends Exception> T prog1E(final SupplierE<? extends T, E> first,
        final ConsumerE<? super T, E>... forms) throws E {

        final var val = first.get();

        for (final var f: list(forms)) { f.accept(val); }

        return val;
    }

    /**
     * evaluate following forms then return first expression evaluation result.
     *
     * @param <T> the type of entire expression
     * @param first evaluation result of this expression
     * @param forms evaluation target forms
     * @return first expression evaluation result
     */
    public static <T> T prog1(final Supplier<? extends T> first, final Statement... forms) {

        final var val = first.get();
        list(forms).each(f -> f.run());
        return val;
    }

    @FunctionalInterface
    public interface WithBlock<X, Y> {

        Y apply(X x) throws IOException;
    }

    public static <T extends Closeable, R> R with(final T res, final WithBlock<T, R> f) throws IOException {
        try (res) { return f.apply(res); }
    }

    /**
     * try-with-resource statement.
     *
     * @param res the resource
     * @param stmt expression body
     */
    public static <T extends AutoCloseable> void letWith(final T res, final Consumer<? super T> stmt) {
        // cast is required to avoid compilation failure on javac
        letWith((Supplier<T>) () -> res, stmt);
    }

    /**
     * try-with-resource statement.
     *
     * @param res the resource
     * @param stmt expression body
     */
    public static <T extends AutoCloseable> void letWith(final Supplier<? extends T> res,
        final Consumer<? super T> stmt) {

        evalWith(res, x -> {
            stmt.accept(x);
            return null;
        });
    }

    /**
     * try-with-resource expression.
     *
     * @param res the resource
     * @param expr expression body
     * @return the value function returned
     */
    public static <T extends AutoCloseable, R> R evalWith(final T res, final Function<? super T, ? extends R> expr) {
        // cast is required to avoid compilation failure on javac
        return evalWith((Supplier<T>) () -> res, expr);
    }

    /**
     * try-with-resource expression.
     *
     * @param res the resource
     * @param expr expression body
     * @return the value function returned
     */
    @SuppressWarnings({ "try", "RedundantSuppression" })
    public static <T extends AutoCloseable, R> R evalWith(final Supplier<? extends T> res,
        final Function<? super T, ? extends R> expr) {

        return eval(() -> {
            try (final T x = res.get()) { return expr.apply(x); }
        });
    }

    /**
     * if-then-else expression.
     *
     * @author takahashikzn
     * @see Expressive#when(BooleanSupplier)
     */
    public interface When {

        /**
         * The value expression treated as the return value of the entire expression if the just before conditional
         * expression evaluated as {@code true}.
         *
         * @param <T> the type of entire expression
         * @param then value expression
         * @return 'then' object
         */
        <T> Then<T> then(Supplier<? extends T> then);

        /**
         * The value treated as the return value of the entire expression if the just before conditional expression
         * evaluated as {@code true}.
         *
         * @param <T> the type of entire expression
         * @param then a value
         * @return 'then' object
         */
        default <T> Then<T> then(final T then) { return this.then(() -> then); }

        /**
         * The body expression of 'if' expression.
         *
         * @param <T> the type of entire expression
         * @author takahashikzn
         */
        interface Then<T> {

            /**
             * Returns the value of entire expression. This is terminal operation.
             *
             * @param none value expression evaluated if and only if all conditional expression evaluated as
             * {@code false}.
             * @return the return value of the entire expression
             */
            T none(Supplier<? extends T> none);

            /**
             * 'else-if' expression.
             *
             * @param when a condition
             * @return 'case' object as an 'else-if' expression.
             */
            Case<T> when(BooleanSupplier when);

            default T none(final T none) { return this.none(() -> none); }

            default Case<T> when(final boolean when) { return this.when(() -> when); }

            default T raise(final Supplier<? extends RuntimeException> raise) {
                return this.none(() -> Expressive.raise(() -> raise.get()));
            }

            default T fatal() { return this.none(() -> Indolently.fatal()); }

            default T fatal(final Object msg) { return this.none(() -> Indolently.fatal(msg)); }
        }

        /**
         * 'if' expression.
         *
         * @param <T> the type of entire expression
         * @author takahashikzn
         */
        interface Case<T> {

            Then<T> then(Supplier<? extends T> then);

            default Then<T> then(final T then) { return this.then(() -> then); }
        }
    }

    /**
     * A shortcut of {@code when(() -> pred)}.
     *
     * @param pred constant conditional value
     * @return 'when' object
     */
    public static When when(final boolean pred) { return when(() -> pred); }

    /**
     * if-then-else expression.
     *
     * <div>
     * Example
     *
     * {@code
     * int x = ...;
     *
     * String evenOrOdd = Expressive
     * .when(() -> x % 2 == 0).then(() -> "even")
     * .when(() -> x % 2 != 0).then(() -> "odd")
     * .none(() -> "This is terminal operation but never called in this example.");
     *
     * // constants are acceptable
     * String simplerEvenOrOdd = Expressive
     * .when(x % 2 == 0).then("even")
     * .when(x % 2 != 0).then("odd")
     * .none("This is terminal operation but never called in this example.");
     * }
     * </div>
     *
     * @param pred first condition
     * @return 'when' object
     */
    public static When when(final BooleanSupplier pred) {

        final Match.IntroCase<?> intro = match(null).when(x -> pred.getAsBoolean());

        return new When() {

            @Override
            public <T> When.Then<T> then(final Supplier<? extends T> then) {

                return new When.Then<T>() {

                    @Override
                    public T none(final Supplier<? extends T> none) {
                        return intro //
                            .then(x -> (T) then.get()) //
                            .none(none);
                    }

                    @Override
                    public When.Case<T> when(final BooleanSupplier when) {
                        return toWhenCase(intro //
                            .then(x -> (T) then.get()) //
                            .when(x -> when.getAsBoolean()));
                    }
                };
            }
        };
    }

    private static <T> When.Case<T> toWhenCase(final Match.Case<?, T> theCase) {

        return then -> new When.Then<T>() {

            @Override
            public T none(final Supplier<? extends T> none) { return theCase.then(then).none(none); }

            @Override
            public When.Case<T> when(final BooleanSupplier when) { return toWhenCase(theCase.then(then).when(when)); }
        };
    }

    @SuppressWarnings({ "overloads", "RedundantSuppression" })
    private static <T> Class<T> argTypeOf(final Function<T, ?> f) {
        return cast(TypeResolver.resolveRawArguments(Function.class, f.getClass())[0]);
    }

    @SuppressWarnings({ "overloads", "RedundantSuppression" })
    private static <T> Class<T> argTypeOf(final Consumer<T> f) {
        return cast(TypeResolver.resolveRawArguments(Consumer.class, f.getClass())[0]);
    }

    public interface Match<C> {

        IntroCase<C> when(Predicate<? super C> pred);

        default IntroCase<C> when(final boolean pred) { return this.when(fixed(pred)); }

        default IntroCase<C> when(final Supplier<? extends C> pred) {
            return this.when(x -> Indolently.equal(x, pred.get()));
        }

        default IntroCase<C> when(final Class<?> type) { return this.when(x -> type.isInstance(x)); }

        default <SC extends C, T> Then<C, T> type(final Function<SC, ? extends T> then) {
            return eval(argTypeOf(then),
                argType -> this.when(argType::isInstance).then(ctx -> then.apply(argType.cast(ctx))));
        }

        interface IntroCase<C> {

            <T> Then<C, T> then(Function<? super C, ? extends T> then);

            default <T> Then<C, T> then(final T then) { return this.then(() -> then); }

            default <T> Then<C, T> then(final Supplier<? extends T> then) { return this.then(x -> then.get()); }
        }

        interface Then<C, T> {

            T none(Function<? super C, ? extends T> none);

            Case<C, T> when(Predicate<? super C> when);

            default Case<C, T> when(final Class<?> type) { return this.when(x -> type.isInstance(x)); }

            default <SC extends C> Then<C, T> type(final Function<SC, ? extends T> then) {

                return eval(argTypeOf(then),
                    argType -> this.when(argType::isInstance).then(ctx -> then.apply(argType.cast(ctx))));
            }

            default Case<C, T> when(final boolean when) { return this.when(fixed(when)); }

            default Case<C, T> when(final BooleanSupplier when) { return this.when(x -> when.getAsBoolean()); }

            default Case<C, T> when(final Supplier<? extends C> pred) {
                return this.when(x -> Indolently.equal(x, pred.get()));
            }

            default T none(final T none) { return this.none(() -> none); }

            default T none(final Supplier<? extends T> none) { return this.none(x -> none.get()); }

            default T raise(final Function<? super C, ? extends RuntimeException> raise) {
                return this.none(x -> Expressive.raise(() -> raise.apply(x)));
            }

            default T fatal() { return this.none(() -> Indolently.fatal()); }

            default T fatal(final Object msg) { return this.none(() -> Indolently.fatal(msg)); }
        }

        interface Case<C, T> {

            Then<C, T> then(Function<? super C, ? extends T> then);

            default Then<C, T> then(final T then) { return this.then(() -> then); }

            default Then<C, T> then(final Supplier<? extends T> then) { return this.then(x -> then.get()); }
        }
    }

    public static <C> Match<C> match(final C ctx) {

        return pred -> new Match.IntroCase<C>() {

            @Override
            public <T> Match.Then<C, T> then(final Function<? super C, ? extends T> then) {
                return Expressive.<C, T> toUnresolvedCase(ctx, pred).then(then);
            }
        };
    }

    private static <C, T> Match.Case<C, T> toResolvedCase(final T value) {

        return new Match.Case<C, T>() {

            @Override
            public Match.Then<C, T> then(final Function<? super C, ? extends T> then) {

                final Match.Case<C, T> self = this;

                return new Match.Then<C, T>() {

                    @Override
                    public T none(final Function<? super C, ? extends T> none) { return value; }

                    @Override
                    public Match.Case<C, T> when(final Predicate<? super C> when) { return self; }
                };
            }
        };
    }

    private static <C, T> Match.Case<C, T> toUnresolvedCase(final C ctx, final Predicate<? super C> condition) {

        final Predicate<? super C> pred = Functional.$(condition).memoize();

        return then -> new Match.Then<C, T>() {

            @Override
            public T none(final Function<? super C, ? extends T> none) {
                return pred.test(ctx) //
                    ? then.apply(ctx) //
                    : none.apply(ctx);
            }

            @Override
            public Match.Case<C, T> when(final Predicate<? super C> when) {
                return pred.test(ctx) //
                    ? toResolvedCase(then.apply(ctx)) //
                    : toUnresolvedCase(ctx, when);
            }
        };
    }
} @SuppressWarnings({ "overloads", "RedundantSuppression" })
public class Functional {

    protected Functional() {}

    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    public static <T> $<T> apply(final $<T> x, final $<T> y, final BiFunction<? super T, ? super T, T> f) {
        return x.map(x0 -> opt(y.map(y0 -> f.apply(x0, y0)).or(x0))).or(y);
    }

    public static <X, Y> Function<X, Y> unbound(final Supplier<? extends Y> f) {
        return x -> f.get();
    }

    public static <X0, X1, R> BiFunction<X0, X1, R> unbound(final Function<? super X1, ? extends R> f) {
        return (x0, x1) -> f.apply(x1);
    }

    public static <X0, X1, X2, R> Function3<X0, X1, X2, R> unbound(
        final BiFunction<? super X1, ? super X2, ? extends R> f) {
        return (x0, x1, x2) -> f.apply(x1, x2);
    }

    public static <X, Y> Supplier<Y> bind(final Function<? super X, ? extends Y> f, final X x) {
        return () -> f.apply(x);
    }

    public static <X0, X1, R> Function<X1, R> bind(final BiFunction<? super X0, ? super X1, ? extends R> f,
        final X0 x0) {
        return x1 -> f.apply(x0, x1);
    }

    public static <X0, X1, X2, Y> BiFunction<X1, X2, Y> bind(
        final Function3<? super X0, ? super X1, ? super X2, ? extends Y> f, final X0 x0) {
        return (x2, x3) -> f.apply(x0, x2, x3);
    }

    public static <X> BooleanSupplier bind(final Predicate<? super X> f, final X x) {
        return () -> f.test(x);
    }

    public static <X0, X1> Predicate<X1> bind(final BiPredicate<? super X0, ? super X1> f, final X0 x0) {
        return x1 -> f.test(x0, x1);
    }

    public static <X0, X1, X2> BiPredicate<X1, X2> bind(final Predicate3<? super X0, ? super X1, ? super X2> f,
        final X0 x0) {
        return (x1, x2) -> f.test(x0, x1, x2);
    }

    public static <T> Supplier<T> memoize(final Supplier<? extends T> f) {
        return bind(memoize((Function<Object, T>) x -> f.get()), null);
    }

    public static <X, Y> Function<X, Y> memoize(final Function<? super X, ? extends Y> f) {

        final BiFunction<X, String, Y> g = memoize((BiFunction<X, String, Y>) (x0, x1) -> f.apply(x0));

        return x -> g.apply(x, "");
    }

    public static <X0, X1, Y> BiFunction<X0, X1, Y> memoize(final BiFunction<? super X0, ? super X1, ? extends Y> f) {

        final Function3<X0, X1, String, Y> g = memoize((Function3<X0, X1, String, Y>) (x0, x1, x2) -> f.apply(x0, x1));

        return (x0, x1) -> g.apply(x0, x1, "");
    }

    public static <X0, X1, X2, Y> Function3<X0, X1, X2, Y> memoize(
        final Function3<? super X0, ? super X1, ? super X2, ? extends Y> f) {

        final Function4<X0, X1, X2, String, Y> g = memoize((x0, x1, x2, x3) -> f.apply(x0, x1, x2));

        return (x0, x1, x2) -> g.apply(x0, x1, x2, "");
    }

    public static <X0, X1, X2, X3, Y> Function4<X0, X1, X2, X3, Y> memoize(
        final Function4<? super X0, ? super X1, ? super X2, ? super X3, ? extends Y> f) {

        final Map<$2<$2<X0, X1>, $2<X2, X3>>, Y> memo = map();

        return (x0, x1, x2, x3) -> {
            synchronized (memo) {
                return memo.computeIfAbsent(tuple(tuple(x0, x1), tuple(x2, x3)), key -> f.apply(x0, x1, x2, x3));
            }
        };
    }

    public static <T> Predicate<T> memoize(final Predicate<? super T> f) {

        final Function<T, Boolean> memoized = memoize(functionOf((final T x) -> f.test(x)));

        return memoized::apply;
    }

    public static <X0, X1> BiPredicate<X0, X1> memoize(final BiPredicate<? super X0, ? super X1> f) {

        final BiFunction<X0, X1, Boolean> memoized = memoize(function2Of((final X0 x0, final X1 x1) -> f.test(x0, x1)));

        return memoized::apply;
    }

    public static <X0, X1, X2> Predicate3<X0, X1, X2> memoize(final Predicate3<? super X0, ? super X1, ? super X2> f) {

        final Function3<X0, X1, X2, Boolean> memoized =
            memoize(function4Of((final X0 x0, final X1 x1, final X2 x2) -> f.test(x0, x1, x2)));

        return memoized::apply;
    }

    public static SBoolSuppl boolsuppl(final Consumer<? super BooleanSupplier> init,
        final Predicate<? super BooleanSupplier> body) {
        return function(init, body);
    }

    public static SBoolSuppl function(final Consumer<? super BooleanSupplier> init,
        final Predicate<? super BooleanSupplier> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SBoolSuppl(self -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.test(self);
        });
    }

    public static <T> SSuppl<T> $(final Supplier<? extends T> suppl) {
        return suppl(suppl);
    }

    public static <T> SSuppl<T> suppl(final Supplier<? extends T> suppl) {
        return suppl(self -> {}, self -> suppl.get());
    }

    public static <T> SSuppl<T> suppl(final Consumer<? super Supplier<T>> init,
        final Function<? super Supplier<? extends T>, ? extends T> body) {
        return function(init, body);
    }

    public static <T> SSuppl<T> function(final Consumer<? super Supplier<T>> init,
        final Function<? super Supplier<? extends T>, ? extends T> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SSuppl<>(self -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.apply(self);
        });
    }

    public static <X, Y> SFunc<X, Y> $(final Function<? super X, ? extends Y> func) {
        return func(func);
    }

    public static <X, Y> SFunc<X, Y> func(final Function<? super X, ? extends Y> func) {
        return func(self -> {}, (self, x) -> func.apply(x));
    }

    public static <X, Y> SFunc<X, Y> func(final Consumer<? super Function<X, Y>> init,
        final BiFunction<? super Function<? super X, ? extends Y>, ? super X, ? extends Y> body) {

        return function(init, body);
    }

    public static <X, Y> SFunc<X, Y> function(final Consumer<? super Function<X, Y>> init,
        final BiFunction<? super Function<? super X, ? extends Y>, ? super X, ? extends Y> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SFunc<>((self, x) -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.apply(self, x);
        });
    }

    public static <X0, X1, Y> SFunc2<X0, X1, Y> $(final BiFunction<? super X0, ? super X1, ? extends Y> func) {
        return func2(func);
    }

    public static <X0, X1, Y> SFunc2<X0, X1, Y> func2(final BiFunction<? super X0, ? super X1, ? extends Y> func) {
        return func2(self -> {}, (self, x0, x1) -> func.apply(x0, x1));
    }

    public static <X0, X1, Y> SFunc2<X0, X1, Y> func2(final Consumer<? super BiFunction<X0, X1, Y>> init,
        final Function3<? super BiFunction<? super X0, ? super X1, ? extends Y>, ? super X0, ? super X1, ? extends Y> body) {

        return function(init, body);
    }

    public static <X0, X1, Y> SFunc2<X0, X1, Y> function(final Consumer<? super BiFunction<X0, X1, Y>> init,
        final Function3<? super BiFunction<? super X0, ? super X1, ? extends Y>, ? super X0, ? super X1, ? extends Y> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SFunc2<>((self, x0, x1) -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.apply(self, x0, x1);
        });
    }

    public static <X0, X1, X2, Y> SFunc3<X0, X1, X2, Y> func3(final Consumer<? super Function3<X0, X1, X2, Y>> init,
        final Function4<? super Function3<? super X0, ? super X1, ? super X2, ? extends Y>, ? super X0, ? super X1, ? super X2, ? extends Y> body) {

        return function(init, body);
    }

    public static <X0, X1, X2, Y> SFunc3<X0, X1, X2, Y> function(final Consumer<? super Function3<X0, X1, X2, Y>> init,
        final Function4<? super Function3<? super X0, ? super X1, ? super X2, ? extends Y>, ? super X0, ? super X1, ? super X2, ? extends Y> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SFunc3<>((self, x0, x1, x2) -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.apply(self, x0, x1, x2);
        });
    }

    public static <X> SPred<X> $(final Predicate<? super X> pred) {
        return pred(pred);
    }

    public static <X> SPred<X> pred(final Predicate<? super X> pred) {
        return pred(self -> {}, (self, x) -> pred.test(x));
    }

    public static <X> SPred<X> pred(final Consumer<? super Predicate<X>> init,
        final BiPredicate<? super Predicate<X>, ? super X> body) {

        return function(init, body);
    }

    public static <X> SPred<X> function(final Consumer<? super Predicate<X>> init,
        final BiPredicate<? super Predicate<X>, ? super X> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SPred<>((self, x) -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.test(self, x);
        });
    }

    public static <X0, X1> SPred2<X0, X1> $(final BiPredicate<X0, X1> pred) {
        return pred2(pred);
    }

    public static <X0, X1> SPred2<X0, X1> pred2(final BiPredicate<X0, X1> pred) {
        return pred2(self -> {}, (self, x0, x1) -> pred.test(x0, x1));
    }

    public static <X0, X1> SPred2<X0, X1> pred2(final Consumer<? super BiPredicate<X0, X1>> init,
        final Predicate3<? super BiPredicate<X0, X1>, ? super X0, ? super X1> body) {

        return function(init, body);
    }

    public static <X0, X1> SPred2<X0, X1> function(final Consumer<? super BiPredicate<X0, X1>> init,
        final Predicate3<? super BiPredicate<X0, X1>, ? super X0, ? super X1> body) {

        requireNonNull(init, "init");
        requireNonNull(body, "body");

        final var initialized = ref(false);

        return new SPred2<>((self, x0, x1) -> {
            synchronized (initialized) {
                initialized.negateIf(false, () -> init.accept(self));
            }

            return body.test(self, x0, x1);
        });
    }

    public static <T> Expression<T> expressionOf(final Expression<? extends T> f) { return cast(f); }

    public static Statement statementOf(final Statement f) { return f; }

    public static <T> Supplier<T> supplierOf(final Supplier<? extends T> f) { return cast(f); }

    public static <X> Consumer<X> consumerOf(final Consumer<? super X> f) { return cast(f); }

    public static <X0, X1> BiConsumer<X0, X1> consumer2Of(final BiConsumer<? super X0, ? super X1> f) {
        return cast(f);
    }

    public static <X0, X1, X2> Consumer3<X0, X1, X2> consumer3Of(
        final Consumer3<? super X0, ? super X1, ? super X2> f) { return cast(f); }

    public static <X0, X1> Function<X0, X1> functionOf(final Function<? super X0, ? extends X1> f) { return cast(f); }

    public static <X0, X1, Y> BiFunction<X0, X1, Y> function2Of(
        final BiFunction<? super X0, ? super X1, ? extends Y> f) { return cast(f); }

    public static <X0, X1, X2, Y> Function3<X0, X1, X2, Y> function4Of(
        final Function3<? super X0, ? super X1, ? super X2, ? extends Y> f) { return cast(f); }

    public static <X> Predicate<X> predicateOf(final Predicate<? super X> f) { return cast(f); }

    public static <X0, X1> BiPredicate<X0, X1> predicate2Of(final BiPredicate<? super X0, ? super X1> f) {
        return cast(f);
    }

    public static <X0, X1, X2> Predicate3<X0, X1, X2> predicate3Of(
        final Predicate3<? super X0, ? super X1, ? super X2> f) { return cast(f); }

    @FunctionalInterface
    public interface ThrowableFunction<X0, X1> {

        X1 apply(X0 x) throws Exception;
    }

    public static <X0, X1> Function<X0, X1> adapt(final ThrowableFunction<X0, X1> f) {
        return x -> {
            try {
                return f.apply(x);
            } catch (final Exception e) {
                return raise(e);
            }
        };
    }

    @FunctionalInterface
    public interface ThrowableFunction2<X0, X1, X2> {

        X2 apply(X0 x0, X1 x1) throws Exception;
    }

    public static <X0, X1, X2> BiFunction<X0, X1, X2> adapt(final ThrowableFunction2<X0, X1, X2> f) {
        return (x0, x1) -> {
            try {
                return f.apply(x0, x1);
            } catch (final Exception e) {
                return raise(e);
            }
        };
    }

    @FunctionalInterface
    public interface ThrowableFunction3<X0, X1, X2, X3> {

        X3 apply(X0 x0, X1 x1, X2 x2) throws Exception;
    }

    public static <X0, X1, X2, X3> Function3<X0, X1, X2, X3> adapt(final ThrowableFunction3<X0, X1, X2, X3> f) {
        return (x0, x1, x2) -> {
            try {
                return f.apply(x0, x1, x2);
            } catch (final Exception e) {
                return raise(e);
            }
        };
    }

    @FunctionalInterface
    public interface ThrowableFunction4<X0, X1, X2, X3, X4> {

        X4 apply(X0 x0, X1 x1, X2 x2, X3 x3) throws Exception;
    }

    public static <X0, X1, X2, X3, X4> Function4<X0, X1, X2, X3, X4> adapt(
        final ThrowableFunction4<X0, X1, X2, X3, X4> f) {
        return (x0, x1, x2, x3) -> {
            try {
                return f.apply(x0, x1, x2, x3);
            } catch (final Exception e) {
                return raise(e);
            }
        };
    }

    public static <X> Supplier<$<X>> soften(final Supplier<X> f) {
        return () -> {
            try { return opt(f.get()); } //
            catch (final RuntimeException e) { return none(); }
        };
    }

    public static <X0, X1> Function<X0, $<X1>> soften(final Function<X0, X1> f) {
        return x -> {
            try { return opt(f.apply(x)); } //
            catch (final RuntimeException e) { return none(); }
        };
    }

    public static <X0, X1, X2> BiFunction<X0, X1, $<X2>> soften(final BiFunction<X0, X1, X2> f) {
        return (x0, x1) -> {
            try { return opt(f.apply(x0, x1)); } //
            catch (final RuntimeException e) { return none(); }
        };
    }

    public static <X0, X1, X2, X3> Function3<X0, X1, X2, $<X3>> soften(final Function3<X0, X1, X2, X3> f) {
        return (x0, x1, x2) -> {
            try { return opt(f.apply(x0, x1, x2)); } //
            catch (final RuntimeException e) { return none(); }
        };
    }

    public static <X> Function<X, Boolean> asFunction(final Predicate<X> pred) {
        return x -> pred.test(x);
    }

    public static <X0, X1> BiFunction<X0, X1, Boolean> asFunction(final BiPredicate<X0, X1> pred) {
        return (x0, x1) -> pred.test(x0, x1);
    }

    public static <X> Predicate<X> asPredicate(final Function<X, Boolean> pred) {
        return x -> pred.apply(x);
    }

    public static <X0, X1> BiPredicate<X0, X1> asPredicate(final BiFunction<X0, X1, Boolean> pred) {
        return (x0, x1) -> pred.apply(x0, x1);
    }
} public static <T> $list<T> list(final $<? extends T> elem) {
    return new $list_impl<T>().push(elem);
}
 public static <F, S> $2<F, S> tuple(final F _1, final S _2) { return new $2<F, S>()._1(_1)._2(_2); }
 @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class Indolently {

    /** non private for subtyping. */
    protected Indolently() { }

    static int idx(final List<?> list, final int idx) {
        return 0 <= idx ? idx : list.size() + idx;
    }

    /**
     * A shortcut of {@code System.currentTimeMillis()}.
     *
     * @return current time in milliseconds.
     */
    public static long now() {
        return System.currentTimeMillis();
    }

    /**
     * Cast the value.
     *
     * @param o the value
     * @return casted value
     */
    @SuppressWarnings("unchecked")
    public static <T> T cast(final Object o) {
        return (T) o;
    }

    public static <IN, OUT> Function<IN, $<OUT>> castTo(final Class<OUT> type) {
        return x -> opt(x).when(type::isInstance).map(type::cast);
    }

    public static <IN, OUT> Function<IN, $<? extends OUT>> castAs(final Class<OUT> type) {
        return x -> opt(x).when(type::isInstance).map(type::cast);
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static int unbox(final Integer x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static long unbox(final Long x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static short unbox(final Short x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static byte unbox(final Byte x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static float unbox(final Float x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static double unbox(final Double x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static char unbox(final Character x) {
        return (x == null) ? 0 : x;
    }

    /**
     * null-safe wrapper to primitive conversion.
     *
     * @param x wrapper value
     * @return primitive value
     */
    public static boolean unbox(final Boolean x) {
        return (x != null) && x;
    }

    public static <T> T fatal() {
        throw new AssertionError();
    }

    public static <T> T fatal(final Object msg) {
        throw new AssertionError(msg);
    }

    public static <T> T TODO() {
        throw new UnsupportedOperationException();
    }

    public static <T> T TODO(final Object msg) {
        throw new UnsupportedOperationException();
    }

    public static <T> T FIXME() {
        throw new UnsupportedOperationException();
    }

    public static <T> T FIXME(final Object msg) {
        throw new UnsupportedOperationException();
    }

    public static <T> T UNSUPPORTED() {
        throw new UnsupportedOperationException();
    }

    public static <T> T UNSUPPORTED(final Object msg) {
        throw new UnsupportedOperationException();
    }

    public static void ASSERT(final boolean flag) { if (!flag) throw new AssertionError(); }

    public static void ASSERT(final boolean flag, final Object msg) {
        if (!flag) throw new AssertionError("" + msg);
    }

    public static void ASSERT(final boolean flag, final Supplier<?> msg) {
        if (!flag) throw new AssertionError("" + msg.get());
    }

    private static final boolean assertive;

    static {
        boolean b;
        try {
            assert false;
            b = false;
        } catch (final AssertionError ignored) {
            b = true;
        }
        assertive = b;
    }

    public static boolean ASSERTIVE() { return assertive; }

    /**
     * An alias of {@link #optionalEmpty(Map)}.
     *
     * @param <T> type of value
     * @param value collection value
     * @return Optional representation of collection
     */
    public static <T extends Map<?, ?>> $<T> nonEmpty(final T value) {
        return optionalEmpty(value);
    }

    /**
     * {@link Optional} representation of collection.
     * Equivalent to {@code empty(col) ? Optional.empty() : Optional.of(col)}.
     *
     * @param <T> type of value
     * @param value collection value
     * @return Optional representation of collection
     * @see #empty(Map)
     */
    public static <T extends Map<?, ?>> $<T> optionalEmpty(final T value) {
        return empty(value) ? $.none() : $.of(value);
    }

    /**
     * An alias of {@link #optionalEmpty(Iterable)}.
     *
     * @param <T> type of value
     * @param value collection value
     * @return Optional representation of collection
     */
    public static <T extends Iterable<?>> $<T> nonEmpty(final T value) {
        return optionalEmpty(value);
    }

    /**
     * {@link Optional} representation of collection.
     * Equivalent to {@code empty(col) ? Optional.empty() : Optional.of(col)}.
     *
     * @param <T> type of value
     * @param value collection value
     * @return Optional representation of collection
     * @see #empty(Iterable)
     */
    public static <T extends Iterable<?>> $<T> optionalEmpty(final T value) {
        return empty(value) ? $.none() : $.of(value);
    }

    /**
     * An alias of {@link #optionalEmpty(CharSequence)}.
     *
     * @param <T> type of value
     * @param value string value
     * @return Optional representation of string
     */
    public static <T extends CharSequence> $<T> nonEmpty(final T value) {
        return optionalEmpty(value);
    }

    /**
     * {@link Optional} representation of string.
     * Equivalent to {@code empty(str) ? Optional.empty() : Optional.of(str)}.
     *
     * @param <T> type of value
     * @param value string value
     * @return Optional representation of string
     * @see #empty(CharSequence)
     */
    public static <T extends CharSequence> $<T> optionalEmpty(final T value) {
        return empty(value) ? $.none() : $.of(value);
    }

    /**
     * An alias of {@link #optionalBlank(CharSequence)}.
     *
     * @param <T> type of value
     * @param value string value
     * @return Optional representation of string
     */
    public static <T extends CharSequence> $<T> nonBlank(final T value) {
        return optionalBlank(value);
    }

    /**
     * {@link Optional} representation of string.
     * Equivalent to {@code blank(str) ? Optional.empty() : Optional.of(str)}.
     *
     * @param <T> type of value
     * @param value string value
     * @return Optional representation of string
     * @see #blank(CharSequence)
     */
    public static <T extends CharSequence> $<T> optionalBlank(final T value) {
        return blank(value) ? $.none() : $.of(value);
    }

    /**
     * An alias of {@link #opt(Object)}.
     *
     * @param <T> type of value
     * @param value the value
     * @return Optional representation of value
     */
    public static <T> $<T> nonNull(final T value) { return opt(value); }

    /**
     * An alias of {@link $#none()}.
     *
     * @return Optional representation of nothing
     */
    public static <T> $<T> none() { return $.none(); }

    /**
     * An alias of {@link Optional#empty()}.
     *
     * @return Optional representation of nothing
     */
    public static <T> Optional<T> none$() { return Optional.empty(); }

    public static <T> T nullable(final $<T> value) { return value.orNull(); }

    public static <T> Function<T, $<T>> opt() { return x -> opt(x); }

    /**
     * An alias of {@link Optional#ofNullable(Object)}.
     *
     * @param <T> type of value
     * @param value the value
     * @return Optional representation of value
     */
    public static <T> $<T> opt(final T value) { return $.of(value); }

    /**
     * An alias of {@link Optional#ofNullable(Object)}.
     *
     * @param <T> type of value
     * @param value the value
     * @param consumers invoked consumers only if value is present
     * @return Optional representation of value
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $<T> opt(final T value, final Consumer<? super T>... consumers) {
        final $<T> opt = opt(value);
        list(consumers).each(f -> opt.tap(f));
        return opt;
    }

    public static <T1, T2, R> $<R> opt(final $<T1> root, final Function<T1, T2> c1, final Function<T2, R> last) {
        return root.map(c1).fmap(opt()).map(last).fmap(opt());
    }

    public static <T1, T2, T3, R> $<R> opt(final $<T1> root, final Function<T1, T2> c1, final Function<T2, T3> c2,
        final Function<T3, R> last) {
        return opt(root, c1, c2).map(last).fmap(opt());
    }

    public static <T1, T2, T3, T4, R> $<R> opt(final $<T1> root, final Function<T1, T2> c1, final Function<T2, T3> c2,
        final Function<T3, T4> c3, final Function<T4, R> last) {
        return opt(root, c1, c2, c3).map(last).fmap(opt());
    }

    public static <T1, T2, T3, T4, T5, R> $<R> opt(final $<T1> root, final Function<T1, T2> c1,
        final Function<T2, T3> c2, final Function<T3, T4> c3, final Function<T4, T5> c4, final Function<T5, R> last) {
        return opt(root, c1, c2, c3, c4).map(last).fmap(opt());
    }

    public static <T1, T2, T3, T4, T5, T6, R> $<R> opt(final $<T1> root, final Function<T1, T2> c1,
        final Function<T2, T3> c2, final Function<T3, T4> c3, final Function<T4, T5> c4, final Function<T5, T6> c5,
        final Function<T6, R> last) {
        return opt(root, c1, c2, c3, c4, c5).map(last).fmap(opt());
    }

    public static <T1, T2, R> $<R> opt(final T1 root, final Function<T1, T2> c1,
        final Function<T2, R> last) { return opt(opt(root), c1, last); }

    public static <T1, T2, T3, R> $<R> opt(final T1 root, final Function<T1, T2> c1, final Function<T2, T3> c2,
        final Function<T3, R> last) { return opt(opt(root), c1, c2, last); }

    public static <T1, T2, T3, T4, R> $<R> opt(final T1 root, final Function<T1, T2> c1, final Function<T2, T3> c2,
        final Function<T3, T4> c3, final Function<T4, R> last) {
        return opt(opt(root), c1, c2, c3, last);
    }

    public static <T1, T2, T3, T4, T5, R> $<R> opt(final T1 root, final Function<T1, T2> c1, final Function<T2, T3> c2,
        final Function<T3, T4> c3, final Function<T4, T5> c4, final Function<T5, R> last) {
        return opt(opt(root), c1, c2, c3, c4, last);
    }

    public static <T1, T2, T3, T4, T5, T6, R> $<R> opt(final T1 root, final Function<T1, T2> c1,
        final Function<T2, T3> c2, final Function<T3, T4> c3, final Function<T4, T5> c4, final Function<T5, T6> c5,
        final Function<T6, R> last) { return opt(opt(root), c1, c2, c3, c4, c5, last); }

    public static <L, R> $$<L, R> left(final L val) { return $$.left(val); }

    public static <L, R> $$<L, R> right(final R val) { return $$.right(val); }

    public static Predicate<$$<?, ?>> isLeft() { return x -> x.isL(); }

    public static Predicate<$$<?, ?>> isRight() { return x -> x.isR(); }

    public static <L, R> Function<L, $$<L, R>> left() { return Indolently::left; }

    public static <L, R> Function<R, $$<L, R>> right() { return Indolently::right; }

    public static final $$.None NONE = $$.None.NONE;

    /**
     * SQL's coalesce function. The name comes from ELVis operator.
     *
     * @param value value
     * @param other default value
     * @return value or default value
     */
    public static <T> T elv(final T value, final T other) { return (value == null) ? other : value; }

    /**
     * SQL's coalesce function. The name comes from ELVis operator.
     *
     * @param value value
     * @param other0 default value
     * @param other1 default value
     * @return value or default value
     */
    public static <T> T elv(final T value, final T other0, final T other1) { return elv(elv(value, other0), other1); }

    /**
     * SQL's coalesce function. The name comes from ELVis operator.
     *
     * @param value value
     * @param other0 default value
     * @param other1 default value
     * @param other2 default value
     * @return value or default value
     */
    public static <T> T elv(final T value, final T other0, final T other1, final T other2) {
        return elv(elv(value, other0, other1), other2);
    }

    /**
     * SQL's coalesce function. The name comes from ELVis operator.
     *
     * @param value value
     * @param other0 default value
     * @param other1 default value
     * @param other2 default value
     * @param other3 default value
     * @return value or default value
     */
    public static <T> T elv(final T value, final T other0, final T other1, final T other2, final T other3) {
        return elv(elv(value, other0, other1, other2), other3);
    }

    public static <T> T elv(final T value, final Supplier<T> other) { return (value == null) ? other.get() : value; }

    public static <T> T elv(final T value, final Supplier<T> other0, final Supplier<T> other1) {
        return elv(elv(value, other0), other1);
    }

    public static <T> T elv(final T value, final Supplier<T> other0, final Supplier<T> other1,
        final Supplier<T> other2) { return elv(elv(value, other0, other1), other2); }

    public static <T> T elv(final T value, final Supplier<T> other0, final Supplier<T> other1, final Supplier<T> other2,
        final Supplier<T> other3) { return elv(elv(value, other0, other1, other2), other3); }

    /**
     * A shortcut notation of {@code Optional.ofNullable(value).map(mapper).orElse(other)}.
     *
     * @param value value
     * @param mapper mapper function
     * @param other default value
     * @return mapped value or default value
     */
    public static <T, S> S optional(final T value, final Function<? super T, S> mapper, final S other) {
        return opt(value).map(mapper).or(other);
    }

    /**
     * A shortcut notation of {@code Optional.ofNullable(value).map(mapper).orElseGet(other)}.
     *
     * @param value value
     * @param mapper mapper function
     * @param other default value supplier
     * @return mapped value or default value
     */
    public static <T, S> S optional(final T value, final Function<? super T, S> mapper, final Supplier<S> other) {
        return opt(value).map(mapper).or(other);
    }

    /**
     * Just an alias of {@link #list(Object...)} but not overloaded one.
     * If compiler fail to do type inference on {@link #list(Object...)}, for example such a
     * {@code List<List<Integer>> nested = list(list(42))}, you can use this method instead of.
     *
     * @param <T> type of value
     * @param elems elements of list
     * @return new list
     * @see #list(Object...)
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $list<T> listOf(final T... elems) {
        return list(elems);
    }

    /**
     * Just an alias of {@link #list(Object...)} but not overloaded one.
     * If compiler fail to do type inference on {@link #list(Object...)} with no argument, for example such a
     * {@code let(list(), x -> x.add("foo"))}, you can use this method instead of.
     *
     * @param <T> type of value
     * @param type type
     * @return new list
     * @see #list(Object...)
     */
    public static <T> $list<T> newList(final Class<T> type) {
        return list();
    }

    /**
     * construct new list which contains specified elements.
     *
     * @param <T> type of value
     * @param elem element of the list
     * @return new list
     */
    public static <T> $list<T> list(final $<? extends T> elem) {
        return new $list_impl<T>().push(elem);
    }

    /**
     * construct new list which contains specified elements.
     *
     * @param <T> type of value
     * @param elems elements of the list
     * @return new list
     */
    public static <T> $list<T> list(final Iterable<? extends T> elems) {
        return new $list_impl<T>().pushAll(opt(elems));
    }

    /**
     * construct new list which contains specified elements.
     *
     * @param <T> type of value
     * @param elems elements of the list
     * @return new list
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $list<T> list(final T... elems) {

        final $list<T> list = new $list_impl<>();

        if (elems != null) {
            Collections.addAll(list, elems);
        }

        return list;
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <V, T extends Predicate<V>> $<T> find(final V cond, final T... preds) {

        for (final T p: preds) {
            if (p.test(cond)) {
                return $.of(p);
            }
        }

        return $.none();
    }

    /**
     * Convert {@link Iterable} to typed array.
     * The array type is same as first element type.
     *
     * @param <T> type of value
     * @param elems elements
     * @return typed array
     * @throws IllegalArgumentException iterable don't contain any element.
     */
    public static <T> T[] array(final Iterable<? extends T> elems) {
        if (empty(elems)) {
            throw new IllegalArgumentException("can't infer empty array type");
        }

        final $list<? extends T> list = list(elems);

        // pseudo typing. actually this type wouldn't be T[].
        @SuppressWarnings({ "unchecked", "SuspiciousArrayCast" })
        final T[] pseudoTyped = (T[]) list.tail().toArray();

        return array(list.head(), pseudoTyped);
    }

    /**
     * Convert arguments to typed array.
     * The array type is same as first element type.
     *
     * @param <T> type of value
     * @param first first element
     * @param rest rest elements
     * @return typed array
     * @throws IllegalArgumentException first element is null..
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression", "unchecked" })
    public static <T> T[] array(final T first, final T... rest) {
        if (first == null) {
            throw new IllegalArgumentException("can't infer empty array type");
        }

        final int len = 1 + ((rest == null) ? 0 : rest.length);

        return list(first) //
            .pushAll(list(rest)) //
            .toArray((T[]) Array.newInstance(first.getClass(), len));
    }

    /**
     * Convert arguments to typed array.
     *
     * @param <T> type of array
     * @param <V> type of value
     * @param type array type
     * @param first first element
     * @param rest rest elements
     * @return typed array
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression", "unchecked" })
    public static <T, V extends T> T[] array(final Class<T> type, final V first, final V... rest) {

        if (first == null) {
            return cast(Array.newInstance(type, 0));
        }

        final int len = 1 + ((rest == null) ? 0 : rest.length);

        return list(first) //
            .pushAll(list(rest)) //
            .toArray((T[]) Array.newInstance(type, len));
    }

    /**
     * Convert arguments to typed array.
     *
     * @param elems elements of array
     * @return {@link Object} array
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> T[] arrayOf(final T... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new Object[] { ... }}.
     *
     * @param elems elements of array
     * @return {@link Object} array
     */
    public static Object[] oarray(final Object... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new char[] { ... }}.
     *
     * @param elems elements of array
     * @return char array
     */
    public static char[] parray(final char... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new int[] { ... }}.
     *
     * @param elems elements of array
     * @return int array
     */
    public static int[] parray(final int... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new long[] { ... }}.
     *
     * @param elems elements of array
     * @return long array
     */
    public static long[] parray(final long... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new float[] { ... }}.
     *
     * @param elems elements of array
     * @return float array
     */
    public static float[] parray(final float... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new byte[] { ... }}.
     *
     * @param elems elements of array
     * @return byte array
     */
    public static byte[] parray(final byte... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new double[] { ... }}.
     *
     * @param elems elements of array
     * @return double array
     */
    public static double[] parray(final double... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new boolean[] { ... }}.
     *
     * @param elems elements of array
     * @return boolean array
     */
    public static boolean[] parray(final boolean... elems) {
        return elems;
    }

    /**
     * The shortcut notation of {@code new byte[] { (byte) 0xFF, ... }}.
     *
     * @param elems elements of array
     * @return int array
     */
    public static byte[] bytes(final int... elems) {

        final byte[] ret = new byte[elems.length];

        for (int i = 0; i < ret.length; i++) {
            ret[i] = (byte) elems[i];
        }

        return ret;
    }

    /**
     * Create an iterator of {@code char}.
     *
     * @param cs character sequence
     * @return char iterator
     */
    public static $iter<Character> chars(final CharSequence cs) {

        return $(new Iterator<Character>() {

            private final int len = cs.length();

            private int pos;

            @Override
            public boolean hasNext() {
                return this.pos < this.len;
            }

            @Override
            public Character next() {
                //noinspection ProhibitedExceptionCaught
                try {
                    return cs.charAt(this.pos++);
                } catch (final IndexOutOfBoundsException e) {
                    throw new NoSuchElementException(e);
                }
            }
        });
    }

    public static <T> $<T> head(final T[] ary) {
        return empty(ary) ? none() : opt(ary[0]);
    }

    public static <T> $<T> last(final T[] ary) {
        return empty(ary) ? none() : opt(ary[ary.length - 1]);
    }

    /**
     * Create a list of {@code char}.
     *
     * @param elems elements of array
     * @return char list
     */
    public static $list<Character> plist(final char... elems) {
        final $list<Character> list = list();
        for (final char e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code int}.
     *
     * @param elems elements of array
     * @return int list
     */
    public static $list<Integer> plist(final int... elems) {
        final $list<Integer> list = list();
        for (final int e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code long}.
     *
     * @param elems elements of array
     * @return long list
     */
    public static $list<Long> plist(final long... elems) {
        final $list<Long> list = list();
        for (final long e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code float}.
     *
     * @param elems elements of array
     * @return float list
     */
    public static $list<Float> plist(final float... elems) {
        final $list<Float> list = list();
        for (final float e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code short}.
     *
     * @param elems elements of array
     * @return short list
     */
    public static $list<Short> plist(final short... elems) {
        final $list<Short> list = list();
        for (final short e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code double}.
     *
     * @param elems elements of array
     * @return double list
     */
    public static $list<Double> plist(final double... elems) {
        final $list<Double> list = list();
        for (final double e: elems) {
            list.add(e);
        }
        return list;
    }

    /**
     * Create a list of {@code boolean}.
     *
     * @param elems elements of array
     * @return boolean list
     */
    public static $list<Boolean> plist(final boolean... elems) {
        final $list<Boolean> list = list();
        for (final boolean e: elems) {
            list.add(e);
        }
        return list;
    }

    public static <T> $set<T> set(final $<? extends T> elem) {
        return new $set_impl<T>().push(elem);
    }

    public static <T> $set<T> set(final Iterable<? extends T> elems) {
        return new $set_impl<T>().pushAll(opt(elems));
    }

    /**
     * Just an alias of {@link #set(Object...)} but not overloaded one.
     * If compiler fail to do type inference on {@link #set(Object...)}, for example such a
     * {@code Set<List<Integer>> nested = set(list(42))}, you can use this method instead of.
     *
     * @param <T> type of value
     * @param elems elements of set
     * @return new set
     * @see #set(Object...)
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $set<T> setOf(final T... elems) {
        return set(elems);
    }

    /**
     * Just an alias of {@link #set(Object...)} but not overloaded one.
     * If compiler fail to do type inference on {@link #set(Object...)}, for example such a
     * {@code let(set(), x -> x.add("foo"))}, you can use this method instead of.
     *
     * @param <T> type of value
     * @param type type
     * @return new set
     * @see #set(Object...)
     */
    public static <T> $set<T> newSet(final Class<T> type) {
        return set();
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $set<T> set(final T... elems) {

        final $set<T> set = new $set_impl<>();

        if (elems != null) {
            set.addAll(list(elems));
        }

        return set;
    }

    public static <K extends Comparable<K>, V> $map<K, V> sort(final Map<? extends K, ? extends V> map) {
        return sort(map, Comparator.naturalOrder());
    }

    public static <K, V, S extends Comparable<S>> $map<K, V> sort(final Map<? extends K, ? extends V> map,
        final Function<? super K, ? extends S> f) {

        return sort(map, Comparator.comparing(f::apply));
    }

    public static <K, V> $map<K, V> sort(final Map<? extends K, ? extends V> map, final Comparator<? super K> comp) {
        return $(ObjFactory.getInstance().<K, V> newSortedMap(Objects.requireNonNull(comp, "comparator"))).pushAll(map);
    }

    public static <T extends Comparable<T>> $set<T> sort(final Set<? extends T> elems) {
        return sort(elems, Comparator.naturalOrder());
    }

    public static <T, S extends Comparable<S>> $set<T> sort(final Set<? extends T> elems,
        final Function<? super T, ? extends S> f) {

        return sort(elems, Comparator.comparing(f::apply));
    }

    public static <T> $set<T> sort(final Set<? extends T> elems, final Comparator<? super T> comp) {
        return $(ObjFactory.getInstance().<T> newSortedSet(Objects.requireNonNull(comp, "comparator"))).pushAll(elems);
    }

    public static <T extends Comparable<T>> $list<T> sort(final List<? extends T> elems) {
        return sort(elems, Comparator.naturalOrder());
    }

    public static <T, S extends Comparable<S>> $list<T> sort(final List<? extends T> elems,
        final Function<? super T, ? extends S> f) {

        return sort(elems, Comparator.comparing(f::apply));
    }

    public static <T> $list<T> sort(final List<? extends T> elems, final Comparator<? super T> comp) {
        final $list<T> rslt = list(elems);
        rslt.sort(Objects.requireNonNull(comp, "comparator"));
        return rslt;
    }

    public static <T> $list<T> uniq(final List<? extends T> elems) {
        return uniq(elems, (x, y) -> equal(x, y));
    }

    public static <T> $list<T> uniq(final List<? extends T> elems, final BiPredicate<? super T, ? super T> f) {

        return $(elems).reduce(list(), (ret, x) -> {
            if (ret.isEmpty() || !ret.some(y -> f.test(x, y))) {
                ret.add(x);
            }

            return ret;
        });
    }

    @SuppressWarnings("rawtypes")
    private static <T> T freeze0(final T x) {
        if (x instanceof Map) return cast(freeze((Map) x));
        if (x instanceof Set) return cast(freeze((Set) x));
        if (x instanceof List) return cast(freeze((List) x));
        return x;
    }

    public static <K, V> $map<K, V> freeze(final Map<? extends K, ? extends V> map) {
        return (map instanceof $map_impl) && (($map_impl<?, ?>) map).frozen()
            ? cast(map)
            : $(Collections.unmodifiableMap($(map).map(Indolently::freeze0)));
    }

    public static <T> $set<T> freeze(final Set<? extends T> set) {
        return (set instanceof $set_impl) && (($set_impl<?>) set).frozen()
            ? cast(set)
            : $(Collections.unmodifiableSet($(set).map(Indolently::freeze0)));
    }

    public static <T> $list<T> freeze(final List<? extends T> list) {
        return (list instanceof $list_impl) && (($list_impl<?>) list).frozen()
            ? cast(list)
            : $(Collections.unmodifiableList($(list).map(Indolently::freeze0)));
    }

    /**
     * test whether the argument is empty or not.
     *
     * @param i test target
     * @return test result
     */
    public static boolean empty(final Iterable<?> i) {
        if (i == null) return true;

        // for optimization
        if (i instanceof Collection) return ((Collection<?>) i).isEmpty();
        if (i instanceof Map) return ((Map<?, ?>) i).isEmpty();
        if (i instanceof Iterator<?>) return !((Iterator<?>) i).hasNext();
        if (i instanceof Enumeration<?>) return !((Enumeration<?>) i).hasMoreElements();

        return !i.iterator().hasNext();
    }

    /**
     * test whether the argument is empty or not.
     *
     * @param i test target
     * @return test result
     */
    public static boolean empty(final Iterable<?>... i) {
        return empty((Object[]) i) || list(i).every(Indolently::empty);
    }

    /**
     * test whether the argument is empty or not.
     *
     * @param map test target
     * @return test result
     */
    public static boolean empty(final Map<?, ?> map) {
        return (map == null) || map.isEmpty();
    }

    /**
     * test whether the argument is empty or not.
     *
     * @param map test target
     * @return test result
     */
    public static boolean empty(final Map<?, ?>... map) {
        return empty((Object[]) map) || list(map).every(Indolently::empty);
    }

    /**
     * test whether the argument is present or not.
     *
     * @param opt test target
     * @return test result
     */
    public static boolean empty(final $<?> opt) { return isNull(opt) || !opt.present(); }

    /**
     * test whether the argument is present or not.
     *
     * @param opt test target
     * @return test result
     */
    public static boolean empty(final $<?>... opt) { return empty((Object[]) opt) || list(opt).every(x -> empty(x)); }

    /**
     * test whether the argument is present or not.
     *
     * @param opt test target
     * @return test result
     */
    public static boolean empty(final Optional<?> opt) { return isNull(opt) || !opt.isPresent(); }

    /**
     * test whether the argument is present or not.
     *
     * @param opt test target
     * @return test result
     */
    public static boolean empty(final Optional<?>... opt) {
        return empty((Object[]) opt) || list(opt).every(x -> empty(x));
    }

    /**
     * test whether the argument is empty string or not.
     *
     * @param cs test target
     * @return test result
     */
    public static boolean empty(final CharSequence cs) {
        return (cs == null) || (cs == "") || (cs.length() == 0);
    }

    /**
     * test whether the argument is empty string or not.
     *
     * @param cs test target
     * @return test result
     */
    public static boolean empty(final CharSequence... cs) {
        return empty((Object[]) cs) || list(cs).every(x -> empty(x));
    }

    public static boolean present(final $<?> opt) {
        return !empty(opt);
    }

    public static boolean presentAny(final $<?> x, final $<?> y, final $<?>... rest) {
        return present(x) || present(y) || list(rest).some(o -> present(o));
    }

    public static boolean presentAll(final $<?> x, final $<?> y, final $<?>... rest) {
        return present(x) && present(y) && list(rest).every(o -> present(o));
    }

    public static boolean presentNone(final $<?> x, final $<?> y, final $<?>... rest) {
        return !presentAny(x, y, rest);
    }

    /**
     * test whether the argument is null or not.
     *
     * @param o test target
     * @return test result
     */
    public static boolean isNull(final Object o) {
        return o == null;
    }

    /**
     * test whether the argument is blank string or not.
     *
     * @param cs test target
     * @return test result
     */
    public static boolean blank(final CharSequence cs) {
        if (empty(cs)) return true;

        // don't use "cs.chars().allMatch(Character::isWhitespace);" for performance
        for (int i = 0, M = cs.length(); i < M; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) return false;
        }

        return true;
    }

    /**
     * test whether the argument is blank string or not.
     *
     * @param cs test target
     * @return test result
     */
    public static boolean blank(final CharSequence... cs) {
        return empty((Object[]) cs) || list(cs).every(Indolently::blank);
    }

    public static boolean empty(final Object[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final byte[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final int[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final long[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final short[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final float[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final double[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final boolean[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean empty(final char[] ary) { return (ary == null) || (ary.length == 0); }

    public static boolean contains(final Object[] ary, final Object val) {
        if (empty(ary)) return false;

        for (final Object x: ary) {
            if (Objects.equals(x, val)) return true;
        }

        return false;
    }

    public static boolean contains(final byte[] ary, final byte val) {
        if (empty(ary)) return false;

        for (final byte x: ary) {
            if (x == val) return true;
        }

        return false;
    }

    public static boolean contains(final int[] ary, final int val) {
        if (empty(ary)) return false;

        for (final int x: ary) {
            if (x == val) return true;
        }

        return false;
    }

    public static boolean contains(final long[] ary, final long val) {
        if (empty(ary)) return false;

        for (final long x: ary) {
            if (x == val) return true;
        }

        return false;
    }

    public static boolean contains(final short[] ary, final short val) {
        if (empty(ary)) return false;

        for (final short x: ary) {
            if (x == val) return true;
        }

        return false;
    }

    public static boolean contains(final float[] ary, final float val) {
        if (empty(ary)) return false;

        for (final float x: ary) {
            if (equal(x, val)) return true;
        }

        return false;
    }

    public static boolean contains(final double[] ary, final double val) {
        if (empty(ary)) return false;

        for (final double x: ary) {
            if (equal(x, val)) return true;
        }

        return false;
    }

    public static boolean contains(final boolean[] ary, final boolean val) {
        if (empty(ary)) return false;

        for (final boolean x: ary)
            if (x == val) return true;

        return false;
    }

    public static boolean contains(final char[] ary, final char val) {
        if (empty(ary)) return false;

        for (final char x: ary)
            if (x == val) return true;

        return false;
    }

    public static boolean contains(final CharSequence cs, final char c) {

        return (cs != null) && (0 < cs.length()) //
            && ((cs instanceof String) ? (0 <= ((String) cs).indexOf(c)) //
            : (cs instanceof StringBuilder) ? (0 <= ((StringBuilder) cs).indexOf(String.valueOf(c))) //
                : (cs instanceof StringBuffer) ? (0 <= ((StringBuffer) cs).indexOf(String.valueOf(c))) //
                    : (0 <= cs.toString().indexOf(c)));
    }

    public static String join(final CharSequence... ary) { return join(list(ary), null); }

    public static String join(final String[] ary, final String sep) { return join(list(ary), sep); }

    public static String join(final Iterable<? extends CharSequence> col) { return join(col, null); }

    public static String join(final Iterable<? extends CharSequence> col, final String sep) {

        return optional(col, x -> {
            final var sj = new StringJoiner(elv(sep, ""));
            col.forEach(sj::add);
            return sj.toString();
        }, (String) null);
    }

    public static byte[] bytes(final String s) { return bytes(s, StandardCharsets.UTF_8); }

    public static byte[] bytes(final String s, final Charset cs) { return s.getBytes(cs); }

    public static String string(final byte[] b) { return string(b, StandardCharsets.UTF_8); }

    public static String string(final byte[] b, final Charset cs) { return new String(b, cs); }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> T choose(final T... elems) {

        return list(elems) //
            .reduce((rem, val) -> rem != null ? rem : val) //
            .orFail(() -> new IllegalArgumentException("all elements are null"));
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> T choose(final Supplier<? extends T>... suppliers) {
        //noinspection RedundantCast
        return choose((T) null, suppliers);
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> T choose(final T initial, final Supplier<? extends T>... suppliers) {

        if (initial != null) return initial;

        if (suppliers != null) {
            for (final var s: suppliers) {
                final var val = s.get();
                if (val != null) return val;
            }
        }

        throw new IllegalArgumentException("all elements are null");
    }

    /**
     * Test that the lower is less than upper.
     * i.e. this method tests {@code l < r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean lt(final double l, final double r) { return Double.compare(l, r) < 0; }

    /**
     * Test that the lower is less equal than upper.
     * i.e. this method tests {@code l <= r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean le(final double l, final double r) { return Double.compare(l, r) <= 0; }

    /**
     * Test that the lower is greater than upper.
     * i.e. this method tests {@code l > r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean gt(final double l, final double r) { return Double.compare(l, r) > 0; }

    /**
     * Test that the lower is greater equal than upper.
     * i.e. this method tests {@code l >= r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean ge(final double l, final double r) { return Double.compare(l, r) >= 0; }

    /**
     * Test that the lower is less than upper.
     * i.e. this method tests {@code l < r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean lt(final long l, final long r) { return l < r; }

    /**
     * Test that the lower is less equal than upper.
     * i.e. this method tests {@code l <= r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean le(final long l, final long r) { return l <= r; }

    /**
     * Test that the lower is greater than upper.
     * i.e. this method tests {@code l > r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean gt(final long l, final long r) { return l > r; }

    /**
     * Test that the lower is greater equal than upper.
     * i.e. this method tests {@code l >= r}.
     *
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static boolean ge(final long l, final long r) { return l >= r; }

    /**
     * Test that the lower is less than upper.
     * i.e. this method tests {@code l < r}.
     *
     * @param <T> value type
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean lt(final T l, final T r) { return l.compareTo(r) < 0; }

    /**
     * Test that the lower is less equal than upper.
     * i.e. this method tests {@code l <= r}.
     *
     * @param <T> value type
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean le(final T l, final T r) { return l.compareTo(r) <= 0; }

    /**
     * Test that the lower is greater than upper.
     * i.e. this method tests {@code l > r}.
     *
     * @param <T> value type
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean gt(final T l, final T r) { return l.compareTo(r) > 0; }

    /**
     * Test that the lower is greater equal than upper.
     * i.e. this method tests {@code l >= r}.
     *
     * @param <T> value type
     * @param l left side value
     * @param r right side value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean ge(final T l, final T r) { return l.compareTo(r) >= 0; }

    /**
     * Test that the value is gerater than lower and less than upper.
     * i.e. this method tests {@code lower < val < upper}.
     *
     * @param <T> value type
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean gtlt(final T l, final T m, final T u) {
        return lt(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less than upper.
     * i.e. this method tests {@code lower <= val < upper}.
     *
     * @param <T> value type
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean gelt(final T l, final T m, final T u) {
        return le(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater than lower and less equal upper.
     * i.e. this method tests {@code lower < val <= upper}.
     *
     * @param <T> value type
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean gtle(final T l, final T m, final T u) {
        return lt(l, m) && le(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less equal upper.
     * i.e. this method tests {@code lower <= val <= upper}.
     *
     * @param <T> value type
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean gele(final T l, final T m, final T u) {
        return le(l, m) && le(m, u);
    }

    /**
     * Test that the value is gerater than lower and less than upper.
     * i.e. this method tests {@code lower < val < upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gtlt(final long l, final long m, final long u) {
        return lt(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less than upper.
     * i.e. this method tests {@code lower <= val < upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gelt(final long l, final long m, final long u) {
        return le(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater than lower and less equal upper.
     * i.e. this method tests {@code lower < val <= upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gtle(final long l, final long m, final long u) {
        return lt(l, m) && le(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less equal upper.
     * i.e. this method tests {@code lower <= val <= upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gele(final long l, final long m, final long u) {
        return le(l, m) && le(m, u);
    }

    /**
     * Test that the value is gerater than lower and less than upper.
     * i.e. this method tests {@code lower < val < upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gtlt(final double l, final double m, final double u) {
        return lt(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less than upper.
     * i.e. this method tests {@code lower <= val < upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gelt(final double l, final double m, final double u) {
        return le(l, m) && lt(m, u);
    }

    /**
     * Test that the value is gerater than lower and less equal upper.
     * i.e. this method tests {@code lower < val <= upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gtle(final double l, final double m, final double u) {
        return lt(l, m) && le(m, u);
    }

    /**
     * Test that the value is gerater equal lower and less equal upper.
     * i.e. this method tests {@code lower <= val <= upper}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean gele(final double l, final double m, final double u) {
        return le(l, m) && le(m, u);
    }

    /**
     * An alias of {@link #gele(Comparable, Comparable, Comparable)}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static <T extends Comparable<T>> boolean between(final T l, final T m, final T u) {
        return gele(l, m, u);
    }

    /**
     * An alias of {@link #gele(long, long, long)}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean between(final long l, final long m, final long u) {
        return gele(l, m, u);
    }

    /**
     * An alias of {@link #gele(double, double, double)}.
     *
     * @param l lower value
     * @param m middle value
     * @param u upper value
     * @return test result
     */
    public static boolean between(final double l, final double m, final double u) {
        return gele(l, m, u);
    }

    public static boolean equal(final long l, final long r) {
        return l == r;
    }

    public static boolean equal(final long l, final long r, final long... rest) {

        if (l != r) {
            return false;
        }

        for (final long x: rest) {
            if (l != x) {
                return false;
            }
        }

        return true;
    }

    public static boolean equal(final double l, final double r) {
        return Double.compare(l, r) == 0;
    }

    public static boolean equal(final double l, final double r, final double... rest) {

        if (Double.compare(l, r) != 0) {
            return false;
        }

        for (final double x: rest) {
            if (Double.compare(l, x) != 0) {
                return false;
            }
        }

        return true;
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T extends Comparable<T>> boolean equal(final T l, final T r, final T... rest) {
        return list(r).pushAll(list(rest)).every(x -> equal(l, x));
    }

    public static boolean equal(final Object l, final Object r, final Object... rest) {
        return list(r).pushAll(list(rest)).every(x -> equal(l, x));
    }

    public static <T extends Comparable<T>> boolean equal(final T l, final T r) {
        return (l == null) ? (r == null) : (r != null) && ((r == l) || (l.compareTo(r) == 0));
    }

    public static boolean equal(final Object l, final Object r) {
        return (l == null) ? (r == null) : (r != null) && ((l == r) || l.equals(r));
    }

    public static boolean eql(final Object l, final Object r) { return equal(l, r); }

    public enum ComparisonResult {

        SMALL(-1), EQUAL(0), LARGE(1);

        public final int sign;

        ComparisonResult(final int sign) {
            this.sign = sign;
        }

        public int sign() {
            return this.sign;
        }

        public int sign(final boolean asc) {
            return asc ? this.sign : -this.sign;
        }

        public int reverse() {
            return -this.sign;
        }
    }

    public static <T extends Comparable<T>> ComparisonResult compare(final T l, final T r) {

        final int rslt = l.compareTo(r);

        if (rslt < 0) {
            return ComparisonResult.SMALL;
        } else if (rslt == 0) {
            return ComparisonResult.EQUAL;
        } else {
            return ComparisonResult.LARGE;
        }
    }

    public static <T extends Comparable<T>> ComparisonResult compare(final Iterable<T> l, final Iterable<T> r) {

        if ((l instanceof List) && (r instanceof List)) {
            return compare((List<T>) l, (List<T>) r);
        }

        for (final Iterator<T> li = l.iterator(), ri = r.iterator(); ; ) {

            final var moreL = li.hasNext();
            final var moreR = ri.hasNext();

            if (moreL && moreR) {
                final var rslt = compare(li.next(), ri.next());

                if (rslt != ComparisonResult.EQUAL) {
                    return rslt;
                }
            } else {
                return compare(moreL ? 1 : 0, moreR ? 1 : 0);
            }
        }
    }

    public static <T extends Comparable<T>> ComparisonResult compare(final List<T> l, final List<T> r) {

        final int lsize = l.size();
        final int rsize = r.size();
        final int len = Math.min(lsize, rsize);

        for (int i = 0; i < len; i++) {

            final var rslt = compare(l.get(i), r.get(i));

            if (rslt != ComparisonResult.EQUAL) {
                return rslt;
            }
        }

        return compare(lsize, rsize);
    }

    @TypeUnsafe
    public static <T> boolean equiv(final T l, final T r) {

        if ((l instanceof Comparable) && (r instanceof Comparable)) {
            return equal(cast(l), cast(r));
        } else {
            return equal(l, r);
        }
    }

    @TypeUnsafe
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> boolean equiv(final T l, final T r, final T... rest) {
        return list(r).pushAll(list(rest)).every(x -> equiv(l, x));
    }

    public static <T extends Comparable<T>> T max(final T l, final T r) {
        return ge(l, r) ? l : r;
    }

    public static <T extends Comparable<T>> T min(final T l, final T r) {
        return le(l, r) ? l : r;
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T extends Comparable<T>> T max(final T first, final T second, final T... rest) {
        return max(list(rest)).map(x -> max(x, max(first, second))).or(() -> max(first, second));
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T extends Comparable<T>> T min(final T first, final T second, final T... rest) {
        return min(list(rest)).map(x -> min(x, min(first, second))).or(() -> min(first, second));
    }

    public static <T extends Comparable<T>> $<T> max(final Iterable<T> values) {
        return list(values).reduce((l, r) -> max(l, r));
    }

    public static <T extends Comparable<T>> $<T> min(final Iterable<T> values) {
        return list(values).reduce((l, r) -> min(l, r));
    }

    public static Class<?> typed(final Class cls) { return cls; }

    public static Map<?, ?> typed(final Map raw) { return raw; }

    public static List<?> typed(final List raw) { return raw; }

    public static Set<?> typed(final Set raw) { return raw; }

    public static <K, V> $map<K, V> map(final Map<? extends K, ? extends V> map) {
        return new $map_impl<K, V>().pushAll(opt(map));
    }

    public static <K, V> $map<K, V> map() { return new $map_impl<>(); }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return argument itself
     * @deprecated this is meaningless method call.
     */
    @Deprecated
    public static <T> $list<T> $(final $list<T> x) {
        return x;
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return argument itself
     * @deprecated this is meaningless method call.
     */
    @Deprecated
    public static <T> $set<T> $(final $set<T> x) {
        return x;
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return argument itself
     * @deprecated this is meaningless method call.
     */
    @Deprecated
    public static <K, V> $map<K, V> $(final $map<K, V> x) {
        return x;
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return clone of the argument
     * @deprecated Use {@link $list#clone()} instead of to get more intentional.
     */
    @Deprecated
    public static <T> $list<T> list(final $list<T> x) {
        return x.clone();
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return clone of the argument
     * @deprecated Use {@link $set#clone()} instead of to get more intentional.
     */
    @Deprecated
    public static <T> $set<T> set(final $set<T> x) {
        return x.clone();
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return clone of the argument
     * @deprecated Use {@link $map#clone()} instead of to get more intentional.
     */
    @Deprecated
    public static <K, V> $map<K, V> map(final $map<K, V> x) {
        return x.clone();
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return argument itself
     * @deprecated this is meaningless method call.
     */
    @Deprecated
    public static <T> $iter<T> $(final $iter<T> x) {
        return x;
    }

    /**
     * Just for producing compilation warning.
     *
     * @param x any wrapped one
     * @return argument itself
     * @deprecated this is meaningless method call.
     */
    @Deprecated
    public static <T> $stream<T> $(final $stream<T> x) {
        return x;
    }

    /**
     * Wrap a map.
     *
     * @param map map to wrap
     * @return wrapped map
     */
    public static <K, V> $map<K, V> $(final Map<K, V> map) {
        return (map == null) ? null //
            : (map instanceof $map) ? cast(map) //
                : new $map_impl<>(map);
    }

    /**
     * Wrap a list.
     *
     * @param list list to wrap
     * @return wrapped list
     */
    public static <T> $list<T> $(final List<T> list) {
        return (list == null) ? null //
            : (list instanceof $list) ? cast(list)//
                : new $list_impl<>(list);
    }

    /**
     * Wrap a set.
     *
     * @param set set to wrap
     * @return wrapped set
     */
    public static <T> $set<T> $(final Set<T> set) {
        return (set == null) ? null //
            : (set instanceof $set) ? cast(set) //
                : new $set_impl<>(set);
    }

    /**
     * Wrap a map.
     *
     * @param map map to wrap
     * @param key key to put
     * @param val value to put
     * @return wrapped map
     */
    public static <K, V> $map<K, V> $(final Map<K, V> map, final K key, final V val) {
        return $(Objects.requireNonNull(map, "map")).push(key, val);
    }

    /**
     * Wrap a list.
     *
     * @param list list to wrap
     * @param elems elements to add
     * @return wrapped list
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $list<T> $(final List<T> list, final T... elems) {
        return $(Objects.requireNonNull(list, "list")).pushAll(list(elems));
    }

    /**
     * Wrap a set.
     *
     * @param set set to wrap
     * @param elems elements to add
     * @return wrapped set
     */
    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> $set<T> $(final Set<T> set, final T... elems) {
        return $(Objects.requireNonNull(set, "set")).pushAll(list(elems));
    }

    /**
     * Wrap a iterator.
     *
     * @param iter iterator to wrap
     * @return wrapped iterator
     */
    public static <T> $iter<T> $(final Iterator<? extends T> iter) {
        if (iter == null) return null;

        if (iter instanceof $iter) return cast(iter);

        return new $iter<T>() {

            @Override
            public boolean hasNext() { return iter.hasNext(); }

            @Override
            public T next() { return iter.next(); }

            @Override
            public void remove() { iter.remove(); }
        };
    }

    /**
     * Wrap a stream.
     *
     * @param stream stream to wrap
     * @return wrapped stream
     */
    public static <T> $stream<T> $(final Stream<T> stream) {
        return (stream == null) ? null //
            : (stream instanceof $stream) ? cast(stream) //
                : new $stream_impl<>(stream);
    }

    public static <K, V> $map<K, V> newMap(final Class<K> keyType, final Class<V> valType) { return map(); }

    @SuppressWarnings("unchecked")
    public static <K, V> $map<K, V> map(final K key, final V val) { return ($map<K, V>) map().push(key, val); }

    @SuppressWarnings("unchecked")
    public static <K, V> $map<K, V> map(final K key, final $<? extends V> val) {
        return ($map<K, V>) map().push(key, val);
    }

    /**
     * create two element tuple.
     *
     * @param _1 1st element
     * @param _2 2nd element
     * @return tuple
     */
    public static <F, S> $2<F, S> tuple(final F _1, final S _2) { return new $2<F, S>()._1(_1)._2(_2); }

    /**
     * create three element tuple.
     *
     * @param _1 1st element
     * @param _2 2nd element
     * @param _3 3rd element
     * @return tuple
     */
    public static <F, S, T> $3<F, S, T> tuple(final F _1, final S _2, final T _3) {
        return new $3<F, S, T>()._1(_1)._2(_2)._3(_3);
    }

    public static <F, S> Function<$2<F, S>, F> _1() { return x -> x._1; }

    public static <F, S> Function<$2<F, S>, S> _2() { return x -> x._2; }

    public static <F, S, T> Function<$3<F, S, T>, F> _1of3() { return x -> x._1; }

    public static <F, S, T> Function<$3<F, S, T>, S> _2of3() { return x -> x._2; }

    public static <F, S, T> Function<$3<F, S, T>, T> _3of3() { return x -> x._3; }

    public static <T, R> Function<List<T>, List<R>> mapl(final Function<T, R> f) {
        return (List<T> list) -> $(list).map(f);
    }

    public static <T, R> Function<Set<T>, Set<R>> maps(final Function<T, R> f) {
        return (Set<T> set) -> $(set).map(f);
    }

    public static <K, T, R> Function<Map<K, T>, Map<K, R>> mapm(final Function<T, R> f) {
        return (Map<K, T> map) -> $(map).map(f);
    }

    /**
     * Convert tuple to list.
     *
     * @param tuple two element tuple
     * @return list of tuple elements
     */
    public static <T> $list<T> list(final $2<? extends T, ? extends T> tuple) { return list(tuple._1, tuple._2); }

    /**
     * Convert tuple to list.
     *
     * @param tuple three element tuple
     * @return list of tuple elements
     */
    public static <T> $list<T> list(final $3<? extends T, ? extends T, ? extends T> tuple) {
        return list(tuple._1, tuple._2, tuple._3);
    }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $bool ref(final boolean val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $int ref(final int val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $long ref(final long val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $double ref(final double val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $float ref(final float val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $short ref(final short val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $byte ref(final byte val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static $char ref(final char val) { return Ref.of(val); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static <T> $void<T> ref(final T val) { return Ref.of(val); }

    /**
     * create an empty reference.
     *
     * @return empty reference
     */
    public static <T> $void<T> ref() { return Ref.of((T) null); }

    /**
     * create a reference of value.
     *
     * @param val initial value
     * @return reference of value
     */
    public static <T extends Comparable<T>> $voidc<T> ref(final T val) { return Ref.of(val); }

    // CHECKSTYLE:OFF
    public static <K, V> $map<K, V> map(final K k0, final V v0, final K k1, final V v1) {
        return map(k0, v0).push(k1, v1);
    }

    public static <K, V> $map<K, V> map(final K k0, final V v0, final K k1, final V v1, final K k2, final V v2) {
        return map(k0, v0, k1, v1).push(k2, v2);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3) {
        return map(k0, v0, k1, v1, k2, v2).push(k3, v3);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4) {
        return map(k0, v0, k1, v1, k2, v2, k3, v3).push(k4, v4);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4, final K k5, final V v5) {
        return map(k0, v0, k1, v1, k2, v2, k3, v3, k4, v4).push(k5, v5);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4, final K k5, final V v5, final K k6, final V v6) {
        return map(k0, v0, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).push(k6, v6);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4, final K k5, final V v5, final K k6, final V v6, final K k7, final V v7) {
        return map(k0, v0, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).push(k7, v7);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4, final K k5, final V v5, final K k6, final V v6, final K k7, final V v7, final K k8, final V v8) {

        return map(k0, v0, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).push(k8, v8);
    }

    public static <K, V> $map<K, V> map( //
        final K k0, final V v0, final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4,
        final V v4, final K k5, final V v5, final K k6, final V v6, final K k7, final V v7, final K k8, final V v8,
        final K k9, final V v9) {
        return map(k0, v0, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).push(k9, v9);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10) {
        return map(k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09,
            v09).push(k10, v10);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10) //
            .push(k11, v11);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11) //
            .push(k12, v12);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12) //
            .push(k13, v13);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13) //
            .push(k14, v14);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14) //
            .push(k15, v15);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15) //
            .push(k16, v16);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16) //
            .push(k17, v17);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17) //
            .push(k18, v18);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18) //
            .push(k19, v19);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19) //
            .push(k20, v20);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20) //
            .push(k21, v21);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21) //
            .push(k22, v22);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22) //
            .push(k23, v23);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23) //
            .push(k24, v24);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24) //
            .push(k25, v25);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25) //
            .push(k26, v26);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26, final K k27, final V v27) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26) //
            .push(k27, v27);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26, final K k27, final V v27,
        final K k28, final V v28) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27) //
            .push(k28, v28);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26, final K k27, final V v27,
        final K k28, final V v28, final K k29, final V v29) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28) //
            .push(k29, v29);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26, final K k27, final V v27,
        final K k28, final V v28, final K k29, final V v29, final K k30, final V v30) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29) //
            .push(k30, v30);
    }

    public static <K, V> $map<K, V> map( //
        final K k00, final V v00, final K k01, final V v01, final K k02, final V v02, final K k03, final V v03,
        final K k04, final V v04, final K k05, final V v05, final K k06, final V v06, final K k07, final V v07,
        final K k08, final V v08, final K k09, final V v09, final K k10, final V v10, final K k11, final V v11,
        final K k12, final V v12, final K k13, final V v13, final K k14, final V v14, final K k15, final V v15,
        final K k16, final V v16, final K k17, final V v17, final K k18, final V v18, final K k19, final V v19,
        final K k20, final V v20, final K k21, final V v21, final K k22, final V v22, final K k23, final V v23,
        final K k24, final V v24, final K k25, final V v25, final K k26, final V v26, final K k27, final V v27,
        final K k28, final V v28, final K k29, final V v29, final K k30, final V v30, final K k31, final V v31) {
        return map( //
            k00, v00, k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, //
            k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, //
            k20, v20, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, //
            k30, v30) //
            .push(k31, v31);
    }

    // CHECKSTYLE:ON

    private static final Function<?, ?> itself = x -> x;

    public static <T> Function<T, T> it() { return itself(); }

    public static <T> Function<T, T> itself() { return cast(itself); }

    public static <T, S> Function<T, S> fixed(final S val) { return x -> val; }

    public static <T> Predicate<T> fixed(final boolean val) { return val ? vrai() : faux(); }

    private static final Predicate<Boolean> asis = x -> x;

    public static Predicate<Boolean> asis() { return asis; }

    private static final Predicate<?> vrai = x -> true;

    public static <T> Predicate<T> vrai() { return cast(vrai); }

    private static final Predicate<?> faux = x -> false;

    public static <T> Predicate<T> faux() { return cast(faux); }

    private static final Predicate<?> nil = x -> x == null;

    public static <T> Predicate<T> nil() { return cast(nil); }

    private static final Predicate<?> nonnil = x -> x != null;

    public static <T> Predicate<T> not(final Predicate<T> f) {
        return (f == nil) ? cast(nonnil) //
            : (f == nonnil) ? cast(nil) //
                : f.negate();
    }

    public static BooleanSupplier and(final BooleanSupplier x0, final BooleanSupplier x1, final BooleanSupplier... x2) {

        return () -> {
            final $list<BooleanSupplier> preds =
                cast(list(Objects.requireNonNull(x0), Objects.requireNonNull(x1)).pushAll(list(x2)));

            return preds.every(BooleanSupplier::getAsBoolean);
        };
    }

    public static boolean and(final boolean x0, final boolean x1, final boolean... x2) {

        if (!x0 || !x1) return false;

        //noinspection ForLoopReplaceableByForEach
        for (int i = 0; i < x2.length; i++) {
            if (!x2[i]) return false;
        }

        return true;
    }

    public static BooleanSupplier or(final BooleanSupplier x0, final BooleanSupplier x1, final BooleanSupplier... x2) {

        return () -> {
            final $list<BooleanSupplier> preds =
                cast(list(Objects.requireNonNull(x0), Objects.requireNonNull(x1)).pushAll(list(x2)));

            return preds.some(BooleanSupplier::getAsBoolean);
        };
    }

    public static boolean or(final boolean x0, final boolean x1, final boolean... x2) {

        if (x0 || x1) return true;

        //noinspection ForLoopReplaceableByForEach
        for (int i = 0; i < x2.length; i++) {
            if (x2[i]) return true;
        }

        return false;
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> Predicate<T> and(final Predicate<? super T> x0, final Predicate<? super T> x1,
        final Predicate<? super T>... x2) {

        return y -> {
            final $list<Predicate<? super T>> preds =
                cast(list(Objects.requireNonNull(x0), Objects.requireNonNull(x1)).pushAll(list(x2)));

            return preds.every(z -> z.test(y));
        };
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> Predicate<T> or(final Predicate<? super T> x0, final Predicate<? super T> x1,
        final Predicate<? super T>... x2) {

        return y -> {
            final $list<Predicate<? super T>> preds =
                cast(list(Objects.requireNonNull(x0), Objects.requireNonNull(x1)).pushAll(list(x2)));

            return preds.some(z -> z.test(y));
        };
    }

    public static <T extends Comparable<T>> Predicate<T> lt(final T r) { return lt(it(), r); }

    public static <T extends Comparable<T>> Predicate<T> le(final T r) { return le(it(), r); }

    public static <T extends Comparable<T>> Predicate<T> gt(final T r) { return gt(it(), r); }

    public static <T extends Comparable<T>> Predicate<T> ge(final T r) { return ge(it(), r); }

    public static <T extends Comparable<T>> Predicate<T> gtlt(final T l, final T u) { return gtlt(it(), l, u); }

    public static <T extends Comparable<T>> Predicate<T> gelt(final T l, final T u) { return gelt(it(), l, u); }

    public static <T extends Comparable<T>> Predicate<T> gtle(final T l, final T u) { return gtle(it(), l, u); }

    public static <T extends Comparable<T>> Predicate<T> gele(final T l, final T u) { return gele(it(), l, u); }

    private static final Predicate<? extends Iterable<?>> hollow = x -> empty(x);

    public static <X extends Iterable<T>, T> Predicate<X> hollow() { return cast(hollow); }

    private static final Predicate<? extends CharSequence> empty = empty(it());

    public static <T extends CharSequence> Predicate<T> empty() { return cast(empty); }

    private static final Predicate<$<?>> present = $::present;

    public static Predicate<$<?>> present() { return present; }

    private static final Predicate<? extends CharSequence> blank = blank(it());

    public static <T extends CharSequence> Predicate<T> blank() { return cast(blank); }

    public static <T> Predicate<T> isa(final Class<?> cls) { return isa(it(), cls); }

    public static Predicate<Class<?>> assignable(final Class<?> cls) { return assignable(it(), cls); }

    public static <T> Predicate<T> same(final T val) { return x -> (x == val); }

    public static <T> Predicate<T> eq(final T val) { return eq(it(), val); }

    public static <T extends Comparable<T>> Predicate<T> eq(final T val) { return eq(it(), val); }

    public static <T> Predicate<T> in(final Collection<? extends T> val) { return in(it(), val); }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <T> Predicate<T> in(final T... val) { return in(it(), val); }

    public static <X, T extends Comparable<T>> Predicate<X> lt(final Function<X, ? extends T> f, final T r) {
        return l -> lt(f.apply(l), r);
    }

    public static <X, T extends Comparable<T>> Predicate<X> le(final Function<X, ? extends T> f, final T r) {
        return l -> le(f.apply(l), r);
    }

    public static <X, T extends Comparable<T>> Predicate<X> gt(final Function<X, ? extends T> f, final T r) {
        return l -> gt(f.apply(l), r);
    }

    public static <X, T extends Comparable<T>> Predicate<X> ge(final Function<X, ? extends T> f, final T r) {
        return l -> ge(f.apply(l), r);
    }

    public static <X, T extends Comparable<T>> Predicate<X> gtlt(final Function<X, ? extends T> f, final T l,
        final T u) {
        return m -> gtlt(l, f.apply(m), u);
    }

    public static <X, T extends Comparable<T>> Predicate<X> gelt(final Function<X, ? extends T> f, final T l,
        final T u) {
        return m -> gelt(l, f.apply(m), u);
    }

    public static <X, T extends Comparable<T>> Predicate<X> gtle(final Function<X, ? extends T> f, final T l,
        final T u) {
        return m -> gtle(l, f.apply(m), u);
    }

    public static <X, T extends Comparable<T>> Predicate<X> gele(final Function<X, ? extends T> f, final T l,
        final T u) {
        return m -> gele(l, f.apply(m), u);
    }

    public static <X, T extends CharSequence> Predicate<X> empty(final Function<X, ? extends T> f) {
        return x -> empty(f.apply(x));
    }

    public static <X, T extends CharSequence> Predicate<X> blank(final Function<X, ? extends T> f) {
        return x -> blank(f.apply(x));
    }

    public static Function<String, Regex> re() { return regex -> re(regex); }

    public static Regex re(final String regex) { return re(regex, "`"); }

    public static Regex re(final String regex, final String escape) {
        return new Regex(Regexive.regex(empty(escape) ? regex : regex.replaceAll(escape, "\\\\")));
    }

    public static Function<String, RegexJDK> re1() { return regex -> re1(regex); }

    public static RegexJDK re1(final String regex) { return re1(regex, "`"); }

    public static RegexJDK re1(final String regex, final String escape) {
        return Regexive.regex1(empty(escape) ? regex : regex.replaceAll(escape, "\\\\"));
    }

    public static Function<String, RegexRe2> re2() { return regex -> re2(regex); }

    public static RegexRe2 re2(final String regex) { return re2(regex, "`"); }

    public static RegexRe2 re2(final String regex, final String escape) {
        return Regexive.regex2(empty(escape) ? regex : regex.replaceAll(escape, "\\\\"));
    }

    public static RegexJDK re(final Pattern regex) { return Regexive.regex1(regex); }

    public static Function<String, ReTest> retest() { return Indolently::retest; }

    public static ReTest retest(final String regex) { return Regexive.tester(regex); }

    public static Function<String, ReTest> refind() { return Indolently::refind; }

    public static ReTest refind(final String regex) {
        final var ptest = retest(regex);

        if (ptest instanceof AutomatonTest) {
            if (ASSERTIVE()) {
                final var pregex = re(regex);
                return ReTest.of(x -> {
                    final var actual = ((AutomatonTest) ptest).find(x);
                    final var expected = pregex.matcher(x).find();
                    assert actual == expected : String.format(
                        "original: %s, automaton: %s, expected: %s, actual: %s, input: %s", regex,
                        ((AutomatonTest) ptest).regex(), expected, actual, x);
                    return actual;
                }, regex);
            }

            return ReTest.of(x -> ((AutomatonTest) ptest).find(x), regex);
        }

        final var pregex = re(regex);
        return ReTest.of(x -> pregex.matcher(x).find(), regex);
    }

    public static <X, T> Predicate<X> nil(final Function<X, ? extends T> f) { return x -> f.apply(x) == null; }

    public static <X, T> Predicate<X> isa(final Function<X, ? extends T> f, final Class<?> cls) {
        return x -> cls.isInstance(f.apply(x));
    }

    public static <X> Predicate<X> assignable(final Function<X, Class<?>> f, final Class<?> cls) {
        return x -> f.apply(x).isAssignableFrom(cls);
    }

    @SuppressWarnings("overloads")
    public static <X, T> Predicate<X> eq(final Function<X, ? extends T> f, final T val) {
        return x -> equal(val, f.apply(x));
    }

    @SuppressWarnings("overloads")
    public static <X, T extends Comparable<T>> Predicate<X> eq(final Function<X, ? extends T> f, final T val) {
        return x -> equal(val, f.apply(x));
    }

    @SafeVarargs
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    public static <X, T> Predicate<X> in(final Function<X, ? extends T> f, final T... val) { return in(f, list(val)); }

    public static <X, T> Predicate<X> in(final Function<X, ? extends T> f, final Collection<? extends T> val) {
        return x -> val.contains(f.apply(x));
    }

    public static DoublePredicate between(final double l, final double u) { return m -> between(l, m, u); }

    public static LongPredicate between(final long l, final long u) { return m -> between(l, m, u); }

    public static IntPredicate between(final int l, final int u) { return m -> between(l, m, u); }

    /**
     * Do nothing Statement.
     *
     * @return do nothing Statement
     */
    public static Statement np() { return Statement.NOP; }

    /**
     * Do nothing Consumer.
     *
     * @return do nothing Consumer
     */
    public static <T> Consumer<T> nop() { return x -> { }; }

    /**
     * Do nothing Consumer.
     *
     * @return do nothing Consumer
     */
    public static <X, Y> BiConsumer<X, Y> noop() { return (x, y) -> { }; }

    public static BiFunction<Number, Number, Integer> sum() { return sum(0); }

    public static BiFunction<Number, Number, Integer> sum(final int z) {
        return (x, y) -> x.intValue() + y.intValue() + z;
    }

    public static BiFunction<Number, Number, Long> sum(final long z) {
        return (x, y) -> x.longValue() + y.longValue() + z;
    }

    public static BiFunction<Number, Number, Float> sum(final float z) {
        return (x, y) -> x.floatValue() + y.floatValue() + z;
    }

    public static BiFunction<Number, Number, Double> sum(final double z) {
        return (x, y) -> x.doubleValue() + y.doubleValue() + z;
    }

    public static int narrow(final int lower, final int x, final int upper) {
        return (x < lower) ? lower : (upper < x) ? upper : x;
    }

    public static int narrow(final int lower, final long x, final int upper) {
        return (int) ((x < lower) ? lower : (upper < x) ? upper : x);
    }

    public static long narrow(final long lower, final long x, final long upper) {
        return (x < lower) ? lower : (upper < x) ? upper : x;
    }

    public static float narrow(final float lower, final float x, final float upper) {
        return (x < lower) ? lower : (upper < x) ? upper : x;
    }

    public static double narrow(final double lower, final double x, final double upper) {
        return (x < lower) ? lower : (upper < x) ? upper : x;
    }

    public static List<String> split(final String s, final char sep) { return split(s, sep, 0, s.length()); }

    public static List<String> split(final String s, final char sep, int from, int to) {
        if (from < 0) { from = s.length() + from; }
        if (to < 0) { to = s.length() + to; }
        checkSplitRange(s, from, to);

        final var chars = s.toCharArray();
        final int begin = from;
        final int end = to;

        final $list<String> ret = list();
        int cur = begin;
        for (int i = cur; i < end; i++) {
            final var c = chars[i];

            if (c == sep) {
                ret.add(s.substring(cur, i));
                cur = i + 1;
            }
        }

        ret.add(s.substring(cur, end));

        return ret;
    }

    public static List<String> split(final String s, final String sep) { return split(s, sep, 0, s.length()); }

    public static List<String> split(final String s, final String sep, int from, int to) {
        final int sl = sep.length();
        if (sl == 0) return list(s);
        if (sl == 1) return split(s, sep.charAt(0), from, to);

        if (from < 0) { from = s.length() + from; }
        if (to < 0) { to = s.length() + to; }
        checkSplitRange(s, from, to);

        final int begin = from;
        final int end = to;

        final $list<String> ret = list();
        int cur = begin;
        for (int i = cur; i < end; i++) {
            if (s.indexOf(sep, cur) == i) {
                ret.add(s.substring(cur, i));
                cur = i + sl;
            }
        }

        ret.add(s.substring(cur, end));

        return ret;
    }

    private static void checkSplitRange(final String s, final int from, final int to) {
        if (to < from) throw new IllegalArgumentException(String.format("to=%d < from=%d", to, from));
        if (s.length() < from || s.length() < to)
            throw new StringIndexOutOfBoundsException(String.format("from=%d, to=%d, len=%d", from, to, s.length()));
    }

    public static <E extends Enum<E>> $<E> enumOf(final Class<E> type, final String name) {
        try { return opt(Enum.valueOf(type, name)); } //
        catch (final IllegalArgumentException e) { return none(); }
    }

    public static <E extends Enum<E>> Function<String, $<E>> enumOf(final Class<E> type) {
        return x -> enumOf(type, x);
    }

    public static <E extends Enum<E>> E[] enumValues(final Class<E> type) {
        //noinspection unchecked
        return (E[]) eval(() -> type.getDeclaredMethod("values").invoke(null));
    }

    public static <E extends Enum<E>> $<E> ienumOf(final Class<E> type, final String name) {
        for (final var e: enumValues(type)) {
            if (e.name().equalsIgnoreCase(name)) return opt(e);
        }
        return none();
    }

    public static <E extends Enum<E>> Function<String, $<E>> ienumOf(final Class<E> type) {
        return x -> ienumOf(type, x);
    }

    public static InputStream bytesIn(final byte[] bin) { return BytesInputStream.create(bin); }

    public static InputStream bytesIn(final ByteArrayOutputStream baos) { return BytesInputStream.create(baos); }

    public static BytesOutputStream bytesOut() { return BytesOutputStream.create(); }

    public static BytesOutputStream bytesOut(final int len) { return BytesOutputStream.create(len); }

    public static byte[] bytes(final InputStream in) throws IOException {
        if (in instanceof ByteArrayInputStream) return in.readAllBytes();

        final var out = bytesOut();
        out.write(in);
        return out.toByteArray();
    }

    public static void shut(final AutoCloseable c) {
        if (c != null) //
            try { c.close(); } //
            catch (final Exception e) { raise(e); }
    }

    public static Consumer<AutoCloseable> shut() { return Indolently::shut; }

    public static void qshut(final AutoCloseable c) {
        if (c != null) //
            try { c.close(); } //
            catch (final Exception e) {
                //noinspection CallToPrintStackTrace
                e.printStackTrace();
            }
    }

    public static Consumer<AutoCloseable> qshut() { return Indolently::qshut; }

    public static String FQCN(final Class<?> cls) { return cls.getName(); }

    public static Promise<Void> async(final RunnableE<? super Exception> run) { return Promissory.async(run); }

    public static Promise<Void> async(final RunnableE<? super Exception> run, final Executor exec) {
        return Promissory.async(run, exec);
    }

    public static <T> Promise<T> async(final Callable<? extends T> run) { return Promissory.async(run); }

    public static <T> Promise<T> async(final Callable<? extends T> run, final Executor exec) {
        return Promissory.async(run, exec);
    }

    public static <T> T await(final Future<? extends T> promise) { return Promissory.await(promise); }

    public static <T> $$<T, $$.None> await(final Future<? extends T> promise, final long timeout) {
        return Promissory.await(promise, timeout);
    }

    public static <T> T await(final Promise<? extends T> promise) { return Promissory.await(promise); }

    public static <T> $$<T, $$.None> await(final Promise<? extends T> promise, final long timeout) {
        return Promissory.await(promise, timeout);
    }

    @SafeVarargs
    public static <T> List<T> await(final Promise<? extends T>... promise) { return await(list(promise)); }

    @SafeVarargs
    public static <T> $$<List<T>, $$.None> await(final long timeout, final Promise<? extends T>... promise) {
        return await(list(promise), timeout);
    }

    public static <T> List<T> await(final Iterable<? extends Promise<? extends T>> promise) {
        return Promissory.await(Promise.all(promise));
    }

    public static <T> $$<List<T>, $$.None> await(final Iterable<? extends Promise<? extends T>> promise,
        final long timeout) { return Promissory.await(Promise.all(promise), timeout); }

    public static <T> Function<Callable<? extends T>, Promise<T>> async() { return Indolently::async; }

    public static Function<Runnable, Promise<Void>> rasync() {
        return x -> async(() -> {
            x.run();
            return null;
        });
    }

    public static <T> Function<Promise<? extends T>, T> await() { return Indolently::await; }

    public static <T> Function<Promise<? extends T>, $$<T, $$.None>> await(final long timeout) {
        return x -> await(x, timeout);
    }

    public static double i2d(final int x) { return x; }

    public static float i2f(final int x) { return x; }

    public static double l2d(final long x) { return x; }

    public static float l2f(final long x) { return x; }

    public static int d2i(final double x) { return (int) x; }

    public static int f2i(final float x) { return (int) x; }

    public static long d2l(final double x) { return (long) x; }

    public static long f2l(final float x) { return (long) x; }

    public static float d2f(final double x) { return (float) x; }

    public static long l2i(final long x) { return (int) x; }

    public static byte i2b(final int x) { return (byte) x; }

    public static byte l2b(final long x) { return (byte) x; }

    public static short i2s(final int x) { return (short) x; }

    public static short l2s(final long x) { return (short) x; }

    public static InputStream openRead(final Path file) throws IOException {
        return new BufferedInputStream(Files.newInputStream(file), 1024 * 1024);
    }

    public static OutputStream openWrite(final Path file) throws IOException {
        return new BufferedOutputStream(Files.newOutputStream(file), 1024 * 1024);
    }

    public static String lcase(final String s) { return s == null ? null : s.toLowerCase(); }

    public static String ucase(final String s) { return s == null ? null : s.toUpperCase(); }

    public static String substr(final String s, final int from) {
        return s == null ? null : substr(s, from, s.length());
    }

    public static String substr(final String s, final int from, final int to) {
        if (s == null) return null;

        final int len = s.length();

        int start = from;
        int end = to;

        if (start < 0) start += len;
        if (end <= 0) end += len;

        return (start < 0 || end < 0 || !between(start, narrow(0, end, len), len))
            ? null
            : s.substring(start, narrow(0, end, len));
    }
}
 public class Iterative {

    /** non private for subtyping. */
    protected Iterative() {}

    /**
     * Generate infinite integer sequence.
     *
     * @param from the value start from (inclusive).
     * @return infinite integer sequence.
     */
    public static $iter<Integer> sequence(final int from) {
        return sequence(from, 1);
    }

    /**
     * Generate infinite integer sequence.
     *
     * @param from the value start from (inclusive).
     * @param step count stepping
     * @return infinite integer sequence.
     */
    public static $iter<Integer> sequence(final int from, final int step) {
        return range(from, Integer.MAX_VALUE, step);
    }

    /**
     * Generate infinite long sequence.
     *
     * @param from the value start from (inclusive).
     * @return infinite integer sequence.
     */
    public static $iter<Long> sequence(final long from) {
        return sequence(from, 1);
    }

    /**
     * Generate infinite long sequence.
     *
     * @param from the value start from (inclusive).
     * @param step count stepping
     * @return infinite integer sequence.
     */
    public static $iter<Long> sequence(final long from, final int step) {
        return range(from, Long.MAX_VALUE, step);
    }

    // @formatter:off
    /**
     * Create iterator which simulates <a
     * href="http://en.wikipedia.org/wiki/Generator_(computer_programming)">generator</a> function.
     *
     * <div>
     * Example
     *
     * {@code
     * // print timestamp every 10 seconds forever.
     * generator(System::currentTimeMillis).forEach(
     *     consumerOf((final Long x) -> System.out.println(Instant.ofEpochMilli(x))).andThen(x -> {
     *         try {
     *             Thread.sleep(10000);
     *         } catch (final InterruptedException e) {
     *             Generator.breaks(); // stop generator gently
     *     }
     * }   ));
     * }
     * </div>
     *
     * @param <T> value type
     * @param f value generating function
     * @return generator as {@link $iter}
     * @see <a href="http://en.wikipedia.org/wiki/Generator_(computer_programming)">Generator_(computer_programming)</a>
     */
    // @formatter:on
    public static <T> Generator<T> generator(final Supplier<? extends T> f) {
        return Generator.of(null, x -> f.get());
    }

    // @formatter:off
    /**
     * Create iterator which simulates <a
     * href="http://en.wikipedia.org/wiki/Generator_(computer_programming)">generator</a> function.
     *
     * <div>
     * Example
     *
     * {@code
     * // print timestamp every 10 seconds forever.
     * generator(
     *     list(),
     *     env -> {
     *         final long now = System.currentTimeMillis();
     *         env.push(now);
     *         return now;
     *     })
     *     .forEach(consumerOf((final Long x) -> {
     *         System.out.println(Instant.ofEpochMilli(x));
     *     })
     *     .andThen(x -> {
     *         try {
     *             Thread.sleep(10000);
     *         } catch (final InterruptedException e) {
     *             Generator.breaks(); // stop generator gently
     *         }
     *     }
     * ));
     * }
     * </div>
     *
     * @param <E> environment type
     * @param <T> value type
     * @param env iteration environment
     * @param f value generating function
     * @return generator as {@link $iter}
     * @see <a href="http://en.wikipedia.org/wiki/Generator_(computer_programming)">Generator_(computer_programming)</a>
     */
    // @formatter:on
    public static <E, T> Generator<T> generator(final E env, final Function<? super E, ? extends T> f) {
        return Generator.of(env, f);
    }

    /**
     * shortcut notation of iterator.
     * This is shortcut notation of creating {@code Iterable<T>}.
     *
     * @param <T> value type
     * @param values lazy evaluated values which {@link Iterator#next} returns
     * @return iterator as {@link $iter}
     */
    @SuppressWarnings({ "varargs", "RedundantSuppression" })
    @SafeVarargs
    public static <T> $iter<T> iterator(final Supplier<? extends T>... values) {

        final Iterator<Supplier<? extends T>> i = list(values).iterator();

        return iterator(i::hasNext, () -> i.next().get());
    }

    /**
     * shortcut notation of iterator.
     * This is shortcut notation of creating {@code Iterable<T>}.
     *
     * @param <T> value type
     * @param hasNext {@link Iterator#hasNext} implementation
     * @param next {@link Iterator#next} implementation
     * @return iterator as {@link $iter}
     */
    public static <T> $iter<T> iterator(final BooleanSupplier hasNext, final Supplier<? extends T> next) {

        return iterator(null, x -> hasNext.getAsBoolean(), x -> next.get());
    }

    /**
     * shortcut notation of iterator.
     * This is shortcut notation of creating {@code Iterable<T>}.
     *
     * @param <E> environment type
     * @param <T> value type
     * @param env iteration environment
     * @param hasNext {@link Iterator#hasNext} implementation
     * @param next {@link Iterator#next} implementation
     * @return iterator as {@link $iter}
     */
    public static <E, T> $iter<T> iterator(final E env, final Predicate<? super E> hasNext,
        final Function<? super E, ? extends T> next) {

        return $iter.of(env, hasNext, next);
    }

    /**
     * Generate integer iterator.
     *
     * <div>
     * Examples
     *
     * <ul>
     * <li>{@code range(1, 3).list()} -&gt; {@code [1, 2, 3]}</li>
     * <li>{@code range(3, 1).list()} -&gt; {@code [3, 2, 1]}</li>
     * <li>{@code range(-3, 1).list()} -&gt; {@code [-3, -2, -1, 0, 1]}</li>
     * </ul>
     * </div>
     *
     * @param from the value start from (inclusive).
     * @param to the value end to (inclusive).
     * @return integer iterator.
     */
    public static $iter<Integer> range(final int from, final int to) {
        return range(from, to, 1);
    }

    /**
     * Generate integer iterator.
     *
     * <div>
     * Examples
     *
     * <ul>
     * <li>{@code range(1, 6, 2).list()} -&gt; {@code [1, 3, 5]}</li>
     * </ul>
     * </div>
     *
     * @param from the value start from (inclusive).
     * @param to the value end to (inclusive).
     * @param step count stepping
     * @return integer iterator.
     */
    public static $iter<Integer> range(final int from, final int to, final int step) {
        //noinspection
        return range((long) from, to, step).map(x -> x.intValue());
    }

    /**
     * Generate long iterator.
     *
     * <div>
     * Examples
     *
     * <ul>
     * <li>{@code range(1, 3).list()} -&gt; {@code [1, 2, 3]}</li>
     * <li>{@code range(3, 1).list()} -&gt; {@code [3, 2, 1]}</li>
     * <li>{@code range(-3, 1).list()} -&gt; {@code [-3, -2, -1, 0, 1]}</li>
     * </ul>
     * </div>
     *
     * @param from the value start from (inclusive).
     * @param to the value end to (inclusive).
     * @return integer iterator.
     */
    public static $iter<Long> range(final long from, final long to) {
        return range(from, to, 1);
    }

    /**
     * Generate long iterator.
     *
     * <div>
     * Examples
     *
     * <ul>
     * <li>{@code range(1, 6, 2).list()} -&gt; {@code [1, 3, 5]}</li>
     * </ul>
     * </div>
     *
     * @param from the value start from (inclusive).
     * @param to the value end to (inclusive).
     * @param step count stepping
     * @return integer iterator.
     */
    public static $iter<Long> range(final long from, final long to, final int step) {
        if (step <= 0) {
            throw new IllegalArgumentException(String.format("(step = %d) <= 0", step));
        }

        final Predicate<$long> pred = //
            env -> when(from < to).then(() -> env.$ <= to) //
                .when(to < from).then(() -> to <= env.$) //
                .none(() -> env.$ == from);

        return iterator(ref(from), pred, env -> match(env) //
            .when(pred).then(x -> x.getThen(y -> y.$ += (from <= to ? step : -step))) //
            .raise(x -> new NoSuchElementException()));
    }

    public static class ResourceIterable<T extends AutoCloseable>
        implements Iterable<T>, AutoCloseable {

        private final Iterable<T> iter;

        private final $list<T> list = list();

        public ResourceIterable(final Iterable<T> iter) { this.iter = iter; }

        @Override
        public void close() throws Exception {
            Exception last = null;
            for (final var r: this.list.pushAll(list(this.iter)))
                try {
                    r.close();
                } catch (final Exception e) {
                    (last = e).printStackTrace();
                }

            if (last != null) throw last;
        }

        @Override
        public Iterator<T> iterator() {

            return new Iterator<>() {

                private final Iterator<T> i = ResourceIterable.this.iter.iterator();

                @Override
                public boolean hasNext() { return this.i.hasNext(); }

                @Override
                public T next() {
                    final var x = this.i.next();
                    ResourceIterable.this.list.add(x);
                    return x;
                }
            };
        }
    }
}
import junitparams.JUnitParamsRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import jp.root42.indolently.function.Function3;
import jp.root42.indolently.function.SFunc;
import jp.root42.indolently.function.SFunc3;
import jp.root42.indolently.ref.$3;
import jp.root42.indolently.ref.$int;
import static jp.root42.indolently.Expressive.*;
import static jp.root42.indolently.Functional.*;
import static jp.root42.indolently.Indolently.list;
import static jp.root42.indolently.Indolently.tuple;
import static jp.root42.indolently.Indolently.*;
import static jp.root42.indolently.Iterative.*;
// Copyright 2014 takahashikzn
//
// 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 jp.root42.indolently;







/**
 * A test class for {@link Functional}.
 *
 * @author takahashikzn
 */
@RunWith(JUnitParamsRunner.class)
public class FunctionalTest {

    /**
     * {@link Functional#function(Consumer, Function3)}
     */
    @Test
    public void testListComprehension() {

        assertThat(
            range(2, 10).filter(z -> func2((final BiFunction<Integer, Integer, Boolean> self) -> {}, (self, x, y) -> {
                if (y <= 1) {
                    return true;
                } else if ((x % y) == 0) {
                    return false;
                } else {
                    return self.apply(x, y - 1);
                }
            }).apply(z, z - 1)) //
                .map(x -> "" + x) //
                .list()) //
            .isEqualTo(list(2, 3, 5, 7).map(x -> "" + x));
    }

    /**
     * fibonacci function.
     */
    @Test
    public void testFunction() {

        final $int initCount = ref(0);

        final Function<Integer, Integer> fib = func( //
            (final Function<Integer, Integer> self) -> {
                assertThat(self.apply(1)).isEqualTo(1); // check no stackoverflow
                initCount.$++;
            }, (self, x) -> //
                (x <= 1) ? x : self.apply(x - 1) + self.apply(x - 2)).memoize();

        final $list<Integer> fibonacciNums =
            list(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711,
                28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887,
                9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296).freeze();

        assertThat(initCount.$).isEqualTo(0);

        assertThat(range(1, 10).each(x -> {
            assertThat(range(0, 42).reduce(list(), (rem, val) -> rem.push(fib.apply(val)))).isEqualTo(fibonacciNums);
            assertThat(initCount.$).isEqualTo(1);
        }).last()).isEqualTo(10);
    }

    /**
     * Tarai function.
     *
     * <pre>
     * def tarai( x, y, z)
     *   if y < x
     *     tarai(
     *          tarai(x-1, y, z),
     *          tarai(y-1, z, x),
     *          tarai(z-1, x, y)
     *        )
     *   else
     *     y          # not z!
     *   end
     * end
     * </pre>
     *
     * @see <a href="http://en.wikipedia.org/wiki/Tak_(function)">tarai function</a>
     */
    @Test
    public void testFunction2() {

        assertThat(func( //
            (final Function<$3<Integer, Integer, Integer>, Integer> self) -> {}, // function decl
            (self, v) -> { // function body

                final int x = v._1;
                final int y = v._2;
                final int z = v._3;

                return when(() -> (y < x)) //
                    .then(() -> (int) self.apply( //
                        tuple( //
                            self.apply(tuple(x - 1, y, z)), //
                            self.apply(tuple(y - 1, z, x)), //
                            self.apply(tuple(z - 1, x, y))))) //
                    .none(y);
            }).memoize().apply(tuple(20, 6, 0))).isEqualTo(20);
    }

    /**
     * Tarai function.
     */
    @Test
    public void testFunction3() {

        final SFunc<$3<Integer, Integer, Integer>, Integer> tarai = func(self -> {}, (self, v) -> {

            final int x = v._1;
            final int y = v._2;
            final int z = v._3;

            return when(() -> (y < x)) //
                .then(() -> (int) self.apply( //
                    tuple( //
                        self.apply(tuple(x - 1, y, z)), //
                        self.apply(tuple(y - 1, z, x)), //
                        self.apply(tuple(z - 1, x, y))))) //
                .none(y);
        });

        assertThat(tarai.memoize().apply(tuple(20, 6, 0))).isEqualTo(20);
    }

    /**
     * Tarai function.
     */
    @Test
    public void testFunction4() {

        assertThat(function( //
            // function decl
            (final Function3<Integer, Integer, Integer, Integer> self) -> {},

            // function body
            (self, x, y, z) -> when(() -> (y < x)) //
                .then(() -> (int) self.apply( //
                    self.apply(x - 1, y, z), //
                    self.apply(y - 1, z, x), //
                    self.apply(z - 1, x, y))).none(y)).memoize().apply(20, 6, 0)).isEqualTo(20);
    }

    /**
     * Tarai function.
     */
    @Test
    public void testFunction5() {

        final SFunc3<Integer, Integer, Integer, Integer> tarai = func3(