Archive for the ‘Functional Programming’ Category
I’ve been reading on F# a bit, and came across it’s ability to do tail call recursion. Tail recursion as defined by Wikipedia:
In computer science, tail recursion (or tail-end recursion) is a special case of recursion in which the last operation of the function, the tail call, is a recursive call. Such recursions can be easily transformed to iterations. Replacing recursion with iteration, manually or automatically, can drastically decrease the amount of stack space used and improve efficiency. This technique is commonly used with functional programming languages, where the declarative approach and explicit handling of state promote the use of recursive functions that would otherwise rapidly fill the call stack.
So, I decided to see if I could implement this in C#, and after a little bit of monkeying around I was able to get something working.
First off, I needed two helper classes, the first of which is the Ref<T> class. It makes it possible to keep track of a reference to an object across closures. There is also an implicit conversion back to the type it is referencing for convenience.
Next was the LazyRef<T>, which is the same as Ref<T> but won’t actually compute the value until it is needed.
Alright, now all that remains is the method that does all of the magic, I’ll present it piecewise then all together at the end. First, let’s look at the method’s signature,
It will return a delegate that represents the tail call optimized method, taking a T as the only parameter and returning an R. The only argument is the target method/delegate to be transformed. Note that the target takes a delegate as it’s first argument, this will be the recurse function that the method will call instead of itself when it wishes to proceed. It then takes a T, and returns a LazyRef to an R.
Now for the first part of the method, just some Ref and LazyRef variables, I’ll explain these as they are used.
Next up is setRef, it’s the function that will be the recurse function that is passed in as the first argument when target is called.
setRef first flips the calledRef flag, so that we know that target wants to do one more recursion, then we store off the value that target wanted to pass on, and we return the lazyResult. lazyResult will return currResult’s value when asked what it’s value is.
Next, is the actual function that is returned,
First off, it sets up the current parameter value as t, since it needs to be set for the first iteration. Then it enters the loop and flips the calledRef flag to false, so if target doesn’t call the recurse function the loop will not continue. After that target is called, passing in setRef as the recurse function, and the current parameter value. It’s return is stored as the currentResult which will be lazyResult until target doesn’t call the recurse function, at which point it will return something else. This goes on until target doesn’t call the recurse function and the loop exits. After that we return the value or lazyResult, which is the value or currentResult. Ok, so here is everything all together:
All of the refs end up in closures in either setRef or the return value, so the values they reference can be shared and changed. Having the current result be lazy in itself makes the whole thing possible. If we didn’t have LazyRef target would be expecting a computed value to be returned from recurse which would require actual recursion.
Time for a quick example, this will run until the x overflows:
Feel free to post questions and comments.