package fj.parser; import fj.F; import static fj.Function.curry; import java.util.Iterator; import java.util.NoSuchElementException; /** * A parse result made up of a value (A) and the remainder of the parse input (I). * * @version %build.number% */ public final class Result<I, A> implements Iterable<A> { private final I i; private final A a; private Result(final I i, final A a) { this.i = i; this.a = a; } /** * The remainder of the parse input. * * @return The remainder of the parse input. */ public I rest() { return i; } /** * The parsed value. * * @return The parsed value. */ public A value() { return a; } /** * Maps the given function across the remainder of the parse input. * * @param f The function to map with. * @return A result with a different parse input. */ public <J> Result<J, A> mapRest(final F<I, J> f) { return result(f.f(i), a); } /** * First-class function mapping across the remainder of the parse input. * * @return A first-class function mapping across the remainder of the parse input. */ public <J> F<F<I, J>, Result<J, A>> mapRest() { return this::mapRest; } /** * Maps the given function across the parse value. * * @param f The function to map with. * @return A result with a different parse value. */ public <B> Result<I, B> mapValue(final F<A, B> f) { return result(i, f.f(a)); } /** * First-class function mapping across the parse value. * * @return A first-class function mapping across the parse value. */ public <B> F<F<A, B>, Result<I, B>> mapValue() { return this::mapValue; } /** * A bifunctor map across both the remainder of the parse input and the parse value. * * @param f The function to map the remainder of the parse input with. * @param g The function to map the parse value with. * @return A result with a different parse input and parse value. */ public <B, J> Result<J, B> bimap(final F<I, J> f, final F<A, B> g) { return mapRest(f).mapValue(g); } /** * First-class bifunctor map. * * @return A first-class bifunctor map. */ public <B, J> F<F<I, J>, F<F<A, B>, Result<J, B>>> bimap() { return curry(this::bimap); } /** * Returns an iterator over the parse value. This method exists to permit the use in a <code>for</code>-each loop. * * @return An iterator over the parse value. */ public Iterator<A> iterator() { return new Iterator<A>() { private boolean r; public boolean hasNext() { return !r; } public A next() { if (r) throw new NoSuchElementException(); else { r = true; return a; } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Construct a result with the given remainder of the parse input and parse value. * * @param i The remainder of the parse input. * @param a The parse value. * @return A result with the given remainder of the parse input and parse value. */ public static <A, I> Result<I, A> result(final I i, final A a) { return new Result<>(i, a); } /** * First-class construction of a result. * * @return A first-class function for construction of a result. */ public static <A, I> F<I, F<A, Result<I, A>>> result() { return curry(Result::result); } }