Resolution: Won't Fix
Affects Version/s: 1.8-beta-4
Fix Version/s: None
Number of attachments :
Closure#trampoline() is good feature but the API is little complicating IMHO.
One reason is Closure#trampoline() has following two meanings:
1) trampoline() is use to initiate trampoline call.
it can be
this is same as the call of (trampoline ...) in Clojure.
2) trampoline() is use to return next call like continuation.
this is same as the return #() form in Clojure.
Those ware difficult to me before understand the logic. Both of those trampoline() return TrampolineClosure instances. So you have to understand the behavior of TrampolineClosure().
My proposal includes two modification to current Trampoline APIs:
- Introduce Closure#tcall(...) method for 1) meaning
- use Closure#call() and TrampolineClosure#call() for 2) meaning.
To replace Closure#call(), change the par-instance metaclass of the original closure instance. This MetaClass change is effective only during tcall() so you can reuse the closure for recursive call if you want.
- current usage of trampoline
- after applying this proposal
The point is, you don't have to modify the body of the original closure which using recursion to which you want to change it to use trampoline call.
The difference is only the method of call to the closure(change call() to tcall()).
And trampoline() and TrampolineClosure instance(returned from trampoline()) are both disappeared from the code.
tcall() make those stuff under the hood.
sample code2(mutual call)
- current usage of trampoline on mutual call
I fell there are too many trampoline() calls here.
- after applying this proposal on mutual call
When using mutual call, what you have to do is the same as self recursion.
Just use tcall() instead of call() to closure to invoke.
To be exact, there is a small difference. In this code, evenp is converted to TrampolineClosure by tcall() but oddp is plain normal closure. But tail call is works well because evenp calls oddp as normal closure so consumes stack one level but oddp returns evenp()'s return value which is TrampolineClosure. So stack is not consumed anymore.
If you want to, by using trampoline() explicitly, you can do exactly same thing to 3-1: