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

com.jnape.palatable.lambda.functions.recursion.Trampoline Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
package com.jnape.palatable.lambda.functions.recursion;

import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.Fn2;
import com.jnape.palatable.lambda.functions.builtin.fn2.Unfoldr;
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult.Recurse;
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult.Terminate;

/**
 * Given an {@link Fn1}<A, {@link CoProduct2}<A, B, ?>> (analogous to "recurse" and "return"
 * tail position instructions, respectively), produce a {@link Fn1}<A, B> that unrolls the original
 * function by iteratively passing each result that matches the input (A) back to the original function,
 * and then terminating on and returning the first output (B).
 * 

* This is isomorphic to - though presumably faster than - taking the last element of an {@link Unfoldr} call. * * @param the trampolined function's input type * @param the trampolined function's output type */ public final class Trampoline implements Fn2>, A, B> { private static final Trampoline INSTANCE = new Trampoline<>(); @Override public B checkedApply(Fn1> fn, A a) { RecursiveResult next = fn.apply(a); while (next instanceof Recurse) next = fn.apply(((Recurse) next).a); return ((Terminate) next).b; } @SuppressWarnings("unchecked") public static Trampoline trampoline() { return (Trampoline) INSTANCE; } public static Fn1 trampoline(Fn1> fn) { return Trampoline.trampoline().apply(fn); } public static B trampoline(Fn1> fn, A a) { return trampoline(fn).apply(a); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy