![]() LambdaĬalculus alone can't do such a thing. Manner, but it doesn't allow by itself to embed recursive calls in a loop. The Y combinator is well known it allows to use lambda functions in a recursive The clean way: modifying the Y combinator I would like to discuss here about my two main functions. Think that most of these solutions don't use Python features otherwise than they should.Ĭlean lambda expressions working along with very standard loops lead to quick, efficient andįully usable tools for implementing tail-recursion optimization.Īs a personal convenience, I wrote a small module implementing such an optimizationīy two different ways. Or very tricky, I think it can be achieved with elegant, short and general solutions I even Optimizing tail-recursion in Python is in fact quite easy. Time rather than only three "Pythonic" functions, working in an interactive session rather than editing my code, etc.). Idea rather than on the process, having twenty short functions on my screen in the same This point of view sometimes however I like trying or implementing new ideasĪs tail-recursive functions rather than with loops for various reasons (focusing on the It has often been claimed that tail-recursion doesn't suit the Pythonic way of coding and that one shouldn't care about how to embed it in a loop. Probably the best high level description I have found for tail calls, recursive tail calls and tail call optimization is the blog postīy Dan Sugalski.I published a module performing tail-call optimization (handling both tail-recursion and continuation-passing style): Optimizing tail-recursion in Python This is because the last thing to happen in any of these functions is to call another function. This below function is TCOptimizable: def fact_h(n, acc): ![]() This function does things besides call another function in its return statement. This optimization can make recursive calls take constant stack space, rather than explode.Įxample: this factorial function is not TCOptimizable: from dis import dis In this case the optimization can be made that g just runs and returns whatever value it would have to the thing that called f. The key here is that f no longer needs stack space - it simply calls g and then returns whatever g would return. The only situation in which this happens is if the last instruction executed in a function f is a call to a function g (Note: g can be f). TCO (Tail Call Optimization) is the process by which a smart compiler can make a call to a function and take no additional stack space. We start with the obvious recursive definition unsigned fac(unsigned n)Īs we can see here, a sufficiently advanced optimizer can replace tail-recursion with iteration, which is far more efficient as you avoid function call overhead and only use a constant amount of stack space. Let's walk through a simple example: the factorial function implemented in C. This is not the case with the non-tail-recursive fact, and as such large values may cause a stack overflow. This means that even if I were to call (fact 1000000), I need only the same amount of space as (fact 3). In contrast, the stack trace for the tail recursive factorial looks as follows: (fact 3)Īs you can see, we only need to keep track of the same amount of data for every call to fact-tail because we are simply returning the value we get right through to the top. As such, the stack looks as follows: (fact 3) ![]() ![]() The first function is not tail recursive because when the recursive call is made, the function needs to keep track of the multiplication it needs to do with the result after the call returns. Scheme is one of the few programming languages that guarantee in the spec that any implementation must provide this optimization, so here are two examples of the factorial function in Scheme: (define (fact x) The most common use is tail-recursion, where a recursive function written to take advantage of tail-call optimization can use constant stack space. Tail-call optimization is where you are able to avoid allocating a new stack frame for a function because the calling function will simply return the value that it gets from the called function. ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |