[Python-ideas] Tail recursion elimination

spir denis.spir at gmail.com
Sun Jan 19 16:07:16 CET 2014


On 01/19/2014 01:45 AM, Steven D'Aprano wrote:
> What makes you say that it is "non-pythonic"? You seem to be assuming
> that *by definition* anything written recursively is non-pythonic. I do
> not subscribe to that view.

It is certainly hard to judge the size of the field of "naturally" recursive 
algorithms. First it depends on applications or application domains, on thinking 
habits, on kinds of data structures... one is accustomed with. Second, there is 
much vagueness and ambiguity on the very term of recursion in programming. 
Recursion and recurrence just mean literally re-running, that is a cyclic, 
repetitive, looping, (re)iterative process.

The typical case used as example is factorial.
	fact(0) = 1      fact(n) = n * fact(n-1)

This is plain semantics. To get an *algorithm* to *compute* fact(n), one can 
interpret these semantics in 2 ways:
* forward iteration: start with base case (0) then as long as we don't reach n 
compute the next factorial
* backward iteration: start with n, then as long as we don't reach the base case 
compute the previous factorial
Both are recursive, but in programming we call the second case a recursion, 
while the former is at times called corecursion (see wikipedia); corecursion is 
just equivalent to plain loops, since moving forward, and just as easy to 
understand. [Which is for the least strange, I'd happily swap the terms.] [And 
the actual computing process of backward iteration is actually forward, indeed, 
but this does not appear in code.]

Funnily enough (since sum is rarely used as example) the trivial case of sum can 
lead to a similar reasoning.

For quite a while I played with mostly functional languages, and as a 
consequence implemented many routines as "backward recursions" (ending with the 
base case), even when back to procedural programming, especially when dealing 
with tree-like or other linked data. I remember a case of a radix trie (see 
wikipedia) which I had a hard time getting right, actually a hard time 
*thinking*. Then by pure chance I stepped on an implementation of tries in 
python, using "forward recursion", which was trivial to understand. I translated 
the logic to my C trie, very happily. This radically changed my view on 
"naturally" recursive algorithms.
That tries (and other linked data when implemented the functional way) are 
*self-similar* (see wikipedia) data structures, that thus corresponding 
algorithms too are "naturally" self-similar, does not imply that *backward* 
recursion is the natural / simple / easy way.

(Now, I do agree that
     def fact (n): return 1 if n<2 else n * fact(n-1)
is very ok: simple and easy enough... once one gets the very principle of 
backward recursion, meaning thinking recurrence so-to-say inside out.)

Denis


More information about the Python-ideas mailing list