There is no concept of time in pure functions.
In imperative programming when two actors approach the same spot, whether the application is parallel or not, one actor ALWAYS arrives first and the other will arrive subsequently. Therefore the Second actor can read the state of the first and act accordingly...
This is not the case for functional programming. Per frame the state of each actor changes (or in other words: new actors with updated states are created) at the same time and thus you can have two actors approach the same spot at the same time. You will then need an extra step for conflict resolution. Of course there's a bunch of ways to deal with this. Carmack briefly mentioned something about using some other attribute of the actor as a priority number... it's not like this is some crazy issue that's impossible to solve.
Very true, but there is a fundamental concept of time, almost by definition, in game-worlds.
Whereas in imperative programming it's true that one actor always arrives first in computation, he might not have arrived first "in the game": conflict resolution is still a necessity.
As such I don't think this is a problem that only occurs in functional programming.
It's my impression that it's the events up to any conflict are much cleaner to express functionally.
FYI I'm not saying either paradigm is worse or better, it is what it is.
Timing is harder to get right when everything is async, but if your game design is good, you just need to better implement it to get it right frame by frame. He also talks about having monads to handle things like this.
In functional programming this can happen... in imperative programming it NEVER happens, because the actors move imperatively, aka step by step or one at a time. This is the problem he is talking about.
* provide an explicit sequencing of when actors take their turns, passing updated resources to each in turn. This is your "step by step" imperative approach, and you're basically writing a main game loop. * don't sequence the actors, but implement a lock on the resource using a TVar. This is the simplest async approach. * many more approaches I haven't thought of
The point of FP is to be provide as much information about the logic of the program as possible. If two actors can move to the same point at the same time, then you need to write down logic to handle that case, whether actors move in sequence or independently.
Not writing down that logic because "I have an imperative language" is how you get bugs, especially race conditions.
Even in the most simple multi-threaded imperative programs, no compiler or hardware will give you almost any sort ordering guarantees by default. You have to use atomics or volatile or something else to get specific ordering guarantees. It's the same in FP compilers too.
Your point? You're saying this as if I disagreed with you. What are you trying to argue here? That FP is the better than imperative? Did I ever dispute that claim? Where are you going with this?
In FP, you will have an immutable variable for state instead of a mutable variable wrapped in a lock. You will be passing a whole new immutable state variable to a pure side effect free function every time, and won't have to worry about getting a lock and releasing it explicitly (these would be side effects). As long as the state is immutable and synced across threads, actors in any thread can just plot their next actions using that state.
In imperative programming, like I said, you'll have to explicitly get and release locks to make sure two actors don't occupy the same spot.
So, if you use atomic immutable variables with pure functions, and the logic in your actors can be conflict free, you can have horizontal scalability across as many cores as you want pretty easily. If your actors cannot be conflict free, you will need to wrap a lock of your choice in a monad and use that, but you will still have gained better debugging, testing and maintainability by using FP.
Now if only every zero-cost OO abstraction had a straight forward FP alternative that was also zero-cost, we'd all be doing FP as of yesterday.
That's not to say that FP is at odds with iterative programming, but it means that you have to work out a "specification" of your code pretty completely from the beginning.
Although, even then it's not so bad because the excellent type systems and compilers mean you can develop the specification interactively (see Idris' typed holes).
Of course there's a level of conflict resolution needed at some point, which wasn't something he had not figured out, but something that was out of line with the elegance and simplicity of how the basic game mechanics were implemented so far.
As I understood if, it's wasn't so much about easy parallel programming as it was his discovery of clean models and elegant solutions as encouraged by functional programming.