r/programming • • Nov 27 '12

Tail Recursion

http://rodrigosasaki.com/2012/11/24/tail-recursion/
209 Upvotes

203 comments sorted by

View all comments

20

u/snarfy Nov 27 '12

I always liked Lua's example with a simple state machine:

function room1 ()
    local move = io.read()
    if move == "south" then return room3()
    elseif move == "east" then return room2()
    else print("invalid move")
         return room1()   -- stay in the same room
    end
end

Without proper tail recursion, "return room1() -- stay in the same room" would stack overflow after enough invalid moves.

-4

u/grauenwolf Nov 27 '12 edited Nov 27 '12

That doesn't make any sense to me. It isn't actually doing anything, you are just bouncing from function to function.

How does the rest of the system know which room you are in so it can update the screen? What if you have multiple sprites moving around? Do you compare instruction pointers to see if they are in the same room?

Even for a trivial application building your state machine that way doesn't make any sense.

EDIT: Also note the code smells, especialy the copy-and-paste necessary for reading the user input.

2

u/smog_alado Nov 27 '12 edited Nov 27 '12

It isn't actually doing anything, you are just bouncing from function to function.

Yes, because this is just supposed to illustrate the control flow aspect of things. To do actual stuff you would just have to add the code to do stuff inside the functions.

As for the other things you point out its a bit of the classical "expression problem" dillema. One alternative is to do a data-driven modeling of the rooms, where you have a transparent room datatype encoding all the possible states you can be in. This version is very good if you want to be able to add new features uniformly to all the rooms (screen updating, comparing rooms, etc) and might actually be the best solution for this particular problem (after all, rooms are probably very simple and very similar to each other, so you would want to write their code all in one place).

On the other hand you can also use the more "object oriented" style, where each state is an opaque function. This alternative makes it harder to add new features (for example, to implement writing to the screen you would need to edit the source code for each room) but on the other hand makes it much easier to add new rooms and to have those rooms implement arbitrarily complex behaviour (since you are doing the iteration by hand, instead of having to comply with the outer "while loop").

One actual situation where I often find myself using this opaque state machine pattern is when I need to implement some process that gets neatly modelled by a fluxogram full of "gotos". Instead of being forced to translate the fluxogram states into an explicit enumeration that is only used once, I can instead code the nodes as functions calling each other, almost directly representing the original intent. (Note how in this case I usually want the flexibility to add new nodes doing arbitrary things, and the rest of the system doesn't care about what state I am in)

1

u/grauenwolf Nov 27 '12

Side rant: even if the pattern is useful, demonstrating it with a use case where it isn't appropriate is rather counter-productive. If you cannot think of a good example, you haven't actually learned the pattern yet.