Reactive, Relational, Functional Programming

Some programming thoughts: but I’m interested in any questions/comments from non-programmers, as well…! Most programming is procedural. (For today’s purposes, we’ll include object-oriented programming as a special case of procedural.) It’s like a script for a play: start at the beginning, and when you get to the end, stop. There are lots of problems with this, the biggest being that it’s very hard to write reliable programs that way, and relatively difficult to maintain them. (I can defend that, but for now, let’s take it as axiomatic.) Functional programming, as in Haskell, works in a more declarative way. Spreadsheet cell functions are kinda like that. Spreadsheet programs are a minimal example of Reactive programming: you (usually) don’t have to tell it to recompute the values; each cell “knows” to update itself when the values that it depends upon are changed. Relational programming is pretty much limited to databases. You don’t really “write a program” in the traditional sense; instead, you describe the type of answer you’d like. For example, “select name from users where age(now() – birthdate) > 18” does not tell the database system how to get the solution. A procedural solution might be something like: “loop for record in table users: when age(now – record.birthdate) > 18, collect; return collected records.” Only, a real database system probably does something much smarter than this. In gaming (among other things), it would be great to combine these. And that’s what I’m trying to work out, for Romance II (the new version of my Massively Multiplayer Online gaming engine). This post is a sort of “rubber duckie” attempt to think them through. In Romance II’s core, we have Entities. An Entity is a thing — any thing. Person, place, event. For example: you are an entity. The screen you’re looking at is, too. And so is this post. And, so is the action of scrolling it. The Reactive part comes in when we start injecting Actions into the model. Suppose, as you’re reading this, a Troll appears behind you. There are two new Entities in the universe: A Troll, and the Action of the Troll’s teleportation. Now, these naturally have effects on the world around them. Trolls, as you probably know, smell very badly. As you probably also remember, teleportation is accompanied by very bright light. Both of these effects, in the real world, you would immediately notice. Let’s call the troll Jan. (“Yawn.”) Jan’s smell is a part of him, just as his greyish-green skin and scraggly, scabby hair. The teleportation is ephemeral, but the light it emits is likewise an attribute of the teleportation. In a Procedural world, like Romance I (used by, e.g. Tootsville), we use an Event Listener system. The teleporter object would do something like this: “ask the room to notify anyone interested that I’m quite shiny.” In turn, while the teleport waited, the room would say, “loop for person in people in this room; notify person of shininess.” Then, each person would, in turn get a chance to react to that shininess; for example, a player-character might write a note like “there is something very shiny happening,” and push it onto the stack of notes waiting to go back to their player, out across the Internet. All of that happens very quickly, but as you can see, it really requires every object to participate. It’s kind of a mess, when you start expanding your types of experiences beyond “shiny.” What happens, you see — and, this is the same as how JavaScript works in your web browser — is that we have to agree upon a pretty comprehensive vocabulary of possible events in advance. Suppose we write a game in which things can enter and exit the room, move around in it, speak, and be shiny or dull. For each type of message, we create handlers in every Object Class… what to do onSomethingEntersRoom, for example. (On the Web, these might be things like onLoad, onClick, and, for a form field, onChange.) Then, we need to have a way for “listeners” who are interested in each type of message to start — and stop — listening, and keep a list of who in each room is listening for each event type; and, likewise, have a routine to tell everyone who’s listening for notifications about Shininess to get those messages. That’s a lot of scaffolding. Then, later, Jan shows up. Our designers are thrilled with Jan. “Look at how his grey-greeniness blends in with the lichen-covered rocks along the Fjords! And just imagine how his overwhelming stench will cause players to retch!” The designers are happy, but as programmers, we sigh. Now, the room will have to have a way to pass messages about stench, as well! And retching! Every new type of event added causes the problem to expand exponentially. But, wait, isn’t that what Reactive programming is for? Why, yes. Yes, it is. So, here is the first major change in Romance II. We have an unified system of listening for certain types of events, like shininess and stench. But, then, you see how I kept saying, “room?” Indeed, most games have a “room” concept. Perhaps a “zone.” Everything that happens in a certain radius may be relayed to everyone in that room (or level, or zone, or whatever). Troll stench, of course, is limited in its range. Beyond a few yards of distance, it’s practically indistinguishable from the cosmic background stench. Shininess, on the other hand, is line of sight. A hefty bookcase might completely obstruct the light of a decent-sized teleport. Following the procedural model, the tempatation would be to handle these things on a case-by-case basis. For example: “loop for person in room: if person can-smell new-stench, then collect person into can-smell-list. Then: loop for person in can-smell-list: notify person of new-stench.” Of course, “can-smell” is going to be very different than “can-see” or “can-hear.” So, again, we have to figure out an appropriate “predicate” (test) for each type of action. It’s also still very procedural. First, we have to look at every person in the room (or world), and decide whether s/he meets the predicate condition (like can-smell). Once we’ve collected that list, then we send each one their notification. We’re also assuming that every notification is going to happen very quickly: essentially, just assume that it’s being tucked away somewhere, to be dealt with later. If any listener wanted to do something more complex, he’d have the ability to make everyone else wait, potentially. Remember my relational example? What if we turn listening on its ear? What if, instead of having to consider each person against a predicate, we instead keyed off that predicate? Imagine this case: “let the stench-smelled for any observer, be: the sum of (the square root of the distance from the observer to the source of the stench, multiplied by the stench of that source).” Now, the observers simply get a notification when the “stench-smelled” changes. By magic. Or something. That is the way I want it to work. *How*, is the next question, and that is why I’m reading up on relational programming, among other things. Thoughts? Opinions? (PS: I’m particularly interested in “non programmer” opinions on these pieces, as I’m intending to collect them into a manuscript at some point.)

(if it looks like I’m drunk, or can’t type, it’s probably because this post came from my mobile.)