From 2ee5789c7739ecb676f57348320c0d845c1a99af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 25 Jul 2020 15:48:21 +0300 Subject: [PATCH] #590 explanation for Trampoline --- trampoline/README.md | 129 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 17 deletions(-) diff --git a/trampoline/README.md b/trampoline/README.md index 2356e8715..8831f41e1 100644 --- a/trampoline/README.md +++ b/trampoline/README.md @@ -9,14 +9,111 @@ tags: --- ## Intent -Trampoline pattern is used for implementing algorithms recursively in Java without blowing the stack -and to interleave the execution of functions without hard coding them together -It is possible by representing a computation in one of 2 states : done | more -(completed with result, or a reference to the reminder of the computation, -something like the way a java.util.Supplier does). + +Trampoline pattern is used for implementing algorithms recursively in Java without blowing the stack and to interleave +the execution of functions without hard coding them together. ## Explanation -Trampoline pattern allows to define recursive algorithms by iterative loop. + +Recursion is a frequently adopted technique for solving algorithmic problems in a divide and conquer +style. For example calculating fibonacci accumulating sum and factorials. In these kinds of problems recursion is +more straightforward than their loop counterpart. Furthermore recursion may need less code and looks more concise. +There is a saying that every recursion problem can be solved using a loop with the cost of writing code that is more +difficult to understand. + +However recursion type solutions have one big caveat. For each recursive call it typically needs an intermediate value +stored and there is a limited amount of stack memory available. Running out of stack memory creates a stack overflow +error and halts the program execution. + +Trampoline pattern is a trick that allows us define recursive algorithms in Java without blowing the stack. + +Real world example + +> A recursive Fibonacci calculation without the stack overflow problem using the Trampoline pattern. + +In plain words + +> Trampoline pattern allows recursion without running out of stack memory. + +Wikipedia says + +> In Java, trampoline refers to using reflection to avoid using inner classes, for example in event listeners. The time overhead of a reflection call is traded for the space overhead of an inner class. Trampolines in Java usually involve the creation of a GenericListener to pass events to an outer class. + +**Programmatic Example** + +Here's the `Trampoline` implementation in Java. + +When `get` is called on the returned Trampoline, internally it will iterate calling `jump` on the returned `Trampoline` +as long as the concrete instance returned is `Trampoline`, stopping once the returned instance is `done`. + +```java +public interface Trampoline { + + T get(); + + default Trampoline jump() { + return this; + } + + default T result() { + return get(); + } + + default boolean complete() { + return true; + } + + static Trampoline done(final T result) { + return () -> result; + } + + static Trampoline more(final Trampoline> trampoline) { + return new Trampoline() { + @Override + public boolean complete() { + return false; + } + + @Override + public Trampoline jump() { + return trampoline.result(); + } + + @Override + public T get() { + return trampoline(this); + } + + T trampoline(final Trampoline trampoline) { + return Stream.iterate(trampoline, Trampoline::jump) + .filter(Trampoline::complete) + .findFirst() + .map(Trampoline::result) + .orElseThrow(); + } + }; + } +} +``` + +Using the `Trampoline` to get Fibonacci values. + +```java + public static Trampoline loop(int times, int prod) { + if (times == 0) { + return Trampoline.done(prod); + } else { + return Trampoline.more(() -> loop(times - 1, prod * times)); + } + } + + log.info("start pattern"); + var result = loop(10, 1).result(); + log.info("result {}", result); + + // start pattern + // result 3628800 +``` ## Class diagram ![alt text](./etc/trampoline.urm.png "Trampoline pattern class diagram") @@ -27,18 +124,16 @@ Use the Trampoline pattern when * For implementing tail recursive function. This pattern allows to switch on a stackless operation. * For interleaving the execution of two or more functions on the same thread. -## Known uses(real world examples) +## Known uses -* Trampoline refers to using reflection to avoid using inner classes, for example in event listeners. -The time overhead of a reflection call is traded for the space overhead of an inner class. -Trampolines in Java usually involve the creation of a GenericListener to pass events to an outer class. - - -## Tutorials - -* [Trampolining: a practical guide for awesome Java Developers](https://medium.com/@johnmcclean/trampolining-a-practical-guide-for-awesome-java-developers-4b657d9c3076) -* [Trampoline in java ](http://mindprod.com/jgloss/trampoline.html) +* [cyclops-react](https://github.com/aol/cyclops-react) ## Credits -* [library 'cyclops-react' uses the pattern](https://github.com/aol/cyclops-react) +* [Trampolining: a practical guide for awesome Java Developers](https://medium.com/@johnmcclean/trampolining-a-practical-guide-for-awesome-java-developers-4b657d9c3076) +* [Trampoline in java ](http://mindprod.com/jgloss/trampoline.html) +* [Laziness, trampolines, monoids and other functional amenities: this is not your father's Java](https://www.slideshare.net/mariofusco/lazine) +* [Trampoline implementation](https://github.com/bodar/totallylazy/blob/master/src/com/googlecode/totallylazy/Trampoline.java) +* [What is a trampoline function?](https://stackoverflow.com/questions/189725/what-is-a-trampoline-function) +* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://www.amazon.com/gp/product/1617293563/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617293563&linkId=ad53ae6f9f7c0982e759c3527bd2595c) +* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://www.amazon.com/gp/product/1617291994/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617291994&linkId=e3e5665b0732c59c9d884896ffe54f4f)