logoalt Hacker News

toast0yesterday at 7:48 PM1 replyview on HN

> My impression is that every tail call can written as a loop much more naturally.

Which is more natural? (please just assume my wonky pseudo code syntax makes sense)

   printall(List) -> 
      foreach item in List {
         print_item(item)
     }.

   printall([Head | Tail]) ->
       print_item(Head),
       printall(Tail);
   printall([]) -> ok.

    
IMHO, both of these need to be taught, neither is particularly more natural. In addition, as others have described, TCO makes a lot of sense for interpreters and state machines.

Replies

10000truthsyesterday at 8:47 PM

> TCO makes a lot of sense for interpreters and state machines.

The reason that performant implementations prefer TCO is because the only reliable knob that clang and gcc provide to control which locals are spilled to stack vs. kept in registers is via calling convention constraints. One could accomplish the same performance without TCO'd recursion if there existed an annotation for local variables designating them as spill/no-spill. But that doesn't exist in clang or gcc - the "register" keyword in the C standard was supposed to be for exactly that, but it's ignored in both compilers.

show 1 reply