Live data from Hacker News

Tail recursion in Python

chrispenner.ca

71–80 of 87 posts

Re: Tail recursion in Python

#72
> It turns out that most recursive functions can be reworked into the tail-call form.

This statement in the beginning is not entirely correct. A more accurate statement would be that all recursive programs that are _iterative_ (if they are loops in disguise), can be rewritten in a tail-call form. That is, there must be a single chain of function calls.

The inherently recursive procedures cannot be converted into a tail-call form.

Re: Tail recursion in Python

#73
Tail recursion is a programming idea left over from the LISP era. It's from when iteration constructs were "while" and "for", and there were no "do this to all that stuff" primitives. Python doesn't really need it.

Re: Tail recursion in Python

#74
post #73

Tail recursion is a programming idea left over from the LISP era. It's from when iteration constructs were "while" and "for", and there were no "do this to all that stuff" primitives. Python doesn't really need it.

Tail calls aren't always just used for some simple iteration. For example, you could have several mutually recursive functions calling each other in tail position. If you wanted to turn that into a loop, you'd have to roll all those functions into a single loop body, which would be made even less elegant due to the lack of goto statement. (TCO essentially turns a call into a goto whenever possible.)

Re: Tail recursion in Python

#76
post #74
post #73

Tail recursion is a programming idea left over from the LISP era. It's from when iteration constructs were "while" and "for", and there were no "do this to all that stuff" primitives. Python doesn't really need it.

Tail calls aren't always just used for some simple iteration. For example, you could have several mutually recursive functions calling each other in tail position. If you wanted to turn that into a loop, you'd have to roll all those functions into a single loop body, which would be made even less elegant due to the lack of goto statement. (TCO essentially turns a call into a goto whenever possible.)

Lots of languages can express it better though - even without gotos. For example in python you can do:

    while some_condition:
        x = one_generator(y)
        y = other_generator(x)
where the generators yield values. No need for goto, no TCO, no magic.

Even in languages like C, a nicer way to express it may be via two explicit state machines rather than going full Duff's device at this problem.

Re: Tail recursion in Python

#77
post #35
post #29

Earlier quoted context omitted.

I've noticed a shift over the last while how privacy-protective people are becoming "out-group" and a little weird. I mean, I personally don't care; I've always been a little weird. But it is funny to see technical preferences as a signaling mechanism. Funny, that is, until it hits a certain point... http://www.wired.co.uk/article/chinese-government-social-cre...

battle is over, privacy lost

Where can I buy your browsing history?

Re: Tail recursion in Python

#78
post #48

This is the same as recur in Clojure. It's not general TCO, though, which is much more powerful. I do think it's a shame that Python doesn't have general TCO. It's said to be unpythonic because it means there will be two ways to do things. But some things are so easily expressed as a recursion but require considerable thought to be turned into a loop.

> But some things are so easily expressed as a recursion but require considerable thought to be turned into a loop. Do you have some examples of problem+solutions where tco works fine (in a language with tco) - but the manual translation is hard(ish)? I wonder in part after reading the Julia thread on tco - and difficulties with providing guarantees in the general case with tco: https://github.com/JuliaLang/julia/iss…

Usually, I implement state machines with mutually tail recursive functions. Each function represents one state.

Re: Tail recursion in Python

#79
post #78
post #48

Earlier quoted context omitted.

> But some things are so easily expressed as a recursion but require considerable thought to be turned into a loop. Do you have some examples of problem+solutions where tco works fine (in a language with tco) - but the manual translation is hard(ish)? I wonder in part after reading the Julia thread on tco - and difficulties with providing guarantees in the general case with tco: https://github.com/JuliaLang/julia/iss…

Usually, I implement state machines with mutually tail recursive functions. Each function represents one state.

Right. The general rewrite would be a loop with a switch and state functions that returned a state? (i was going to say state functions that called back to a step function, but I guess that'd still build a call stack).

Re: Tail recursion in Python

#80

This is the same as recur in Clojure. It's not general TCO, though, which is much more powerful. I do think it's a shame that Python doesn't have general TCO. It's said to be unpythonic because it means there will be two ways to do things. But some things are so easily expressed as a recursion but require considerable thought to be turned into a loop.

> I do think it's a shame that Python doesn't have general TCO. It's said to be unpythonic because it means there will be two ways to do things.

The usual complaint I hear is about stack traces, not “two ways to do things”, which Python rather often provides anyway.

Post reply on HN