In the next few weeks I’ll be putting together a release of Minnow with enough of the language implemented you can play with it to see what it will feel like, but before I did that I just wanted to share a bit of Minnow code.
This bit of code is the Minnow solution to the Computer Language Benchmark Game’s threadring benchmark (description of the benchmark at the bottom of the page).
EDIT: the source below is now out of date with the current minnow syntax. A similar example is given in the ./samples directory of the release.
actor passer var int m_id var passer m_next action pass(int token) if (token == 0) puti(m_id) exit(0) else token = token - 1 m_next::pass(token) end end action setIdAndNext(int id, passer next) m_id = id m_next = next end end action main(stringvector args) spawn passer passers[503] var int i = 0 while (i < 502) passers[i]::setIdAndNext(i+1, passers[i+1]) i = i + 1 end passers[502]::setIdAndNext(503, passers[0]) passers[0]::pass(convertToInt(args[0])) end
Let me touch on a few bits that might seem a little out of the norm.
- The keyword ’spawn’ not only creates a variable to hold an actor, but also spawns that actor onto its own thread. After the spawn command actors are immediately ready to receive messages.
- The “::” notation, which I borrowed from C++, is to denote one of the two types of message passing in Minnow. In Minnow, the messages you send actors are:
- Action messages: messages that tell the actor what the next task/action to do is. These use the “::” notation, and, as you might also notice, resemble a method call on an object.
- Data messages: messages that give the actor more information while an actor is in the middle of a task. If you’re familiar with Erlang, you can think of Erlang’s message passing scheme and Minnow’s data messages as synonymous.
- Lastly, you might also notice we don’t explicitly wait for actions. In Minnow, since this happens frequently, an actor will automatically wait for the next task as it finishes the previous one.
Interesting. However, I’m not sure I like the idea of mutable state, especially in a language which is attempting to simplify parallel programming. I’m certainly not a purist about it, I have nothing *against* imperative languages per se; but mutable state *kills* concurrency, even when using actor abstractions.
Aside from treating actors like sort-of monads, does Minnow actually support higher-order constructs? If it does, then I suppose it would be possible to avoid mutable state for the most part, it would just take a bit of self-control.
To my knowledge, mutable state doesn’t kill concurrency, but shared state does, since you’re going to spend your time synchronizing instead of doing useful work.
In Minnow there is no shared state. The finished language will allow you to chose between a scope-enforced pass-by-handoff, or simply by copying what you wish to send.
Monads, too, have a problem in that they aren’t concurrent. By definition they define a string of things that must be done in order.
Instead, what is more helpful is to talk about the system as connected autonomous actors, so that you can use analysis to see how best to lay these actors on the hardware (you can see my Minnow talk for a light introduction, or dive into the StreamIT papers for more information)
The finished Minnow will allow higher order automation.