(The usual pattern is "transform :: world state 1 -> world state 2". The transformer can "modify" as much of state 1 as it wants.)
(The usual pattern is "transform :: world state 1 -> world state 2". The transformer can "modify" as much of state 1 as it wants.)
How is passing around world state from one transformer function to another an improvement over traditional stateful programming where functions change variables?
Though it would be interesting hear how people who have been doing FP for a while handle it.
"Premature optimization is the root of all evil."
Computers are fast. On my machine, I can allocate, initialize, and garbage collect almost 4G of memory a second. This sort of thing is really fast, and is unlikely to be a performance problem.
When all of your data is immutable, however, you can reuse the data that you didn't change. The canonical example is a binary tree consisting of 2^n nodes. Changing one node only requires you to allocate n new nodes. As your tree gets bigger, the copying overhead goes to 0.
In the case of Haskell, the compiler is smart enough to figure this all out for you. So all you need to do is write correct code, and let the compiler make it work on a machine.
(It's also theoretically possible to reuse structures by mutating them instead of collecting-and-reallocating. You don't do that as part of your game, though, you let the compiler's optimizer do it. It will do it right, you will do it wrong.)
When everything has to happen in 1/60th of a second, then all that garbage collection is a serious problem. Memory allocation and deallocation is expensive in games, especially on the consoles.
For simpler games, yes, not a problem.
But the problem is valid. In games every nanosecond counts, which is why the control manual memory allocation offers is so attractive.
It's a problem that even small, single-unit game developers have. On the indie game dev forums, fighting against the .Net/Java GC is a common topic. When the GC kicks in, your framerate usually suffers and you waste productivity with tricks to avoid triggering it. When you have multiple cores, asynchronous GPUs and multi-threaded OSes it affects anything other than the most basic of games.
Having said that, in http://lambda-the-ultimate.org/node/1277 Tim Sweeney (of Epic, developers of Gears of War and the Unreal Engine middleware) says:
"Will gladly sacrifice 10% of our performance for 10% higher productivity" and also "Garbage collection should be the only option"
That presentation is a good summary of the current situation of AAA-games programming (well, three years old, but still) and why Epic are programming in C++ and not Haskell or some other functional language, even though they'd like to. Well worth a read.