I’m having trouble being happy. So far, 2007 hasn’t been very fulfilling or satisfying.
A lot of stuff is different this year than it has been in other years. The most obvious thing is that I’m not in school. That could have a lot to do with it. I feel my brain settling into its patterns, optimizing for my lifestyle and minimizing its energy usage. This never happened in school; I always felt like by brain was exercising and stretching, and now it’s sitting on its lazy ass in front of the game programming TV. I’ve hardly been doing any math; I haven’t come any closer to my goal of understanding the independence of CH from ZF.
But I’m afraid of going back to school. There is too much bullshit there. I want to learn, I want to work hard and stretch my brain, but I don’t want to fuck with that awful thing called homework which deprives me of relaxation every hour of the week. I’m not enjoying working at NetDevil very much, but I am really enjoying the working model—go into work, do stuff, come home, relax and sleep. It beats school: go to school, listen to stuff, come home, work, maybe sleep. I don’t want to mess with intro to voice class teachers who have meaningless expectations. At work, I can argue with my lead programmer and the director about the benefits of doing a task, so I don’t get caught doing meaningless stuff. I can’t do that with a teacher.
I want to go to school and take a bunch of linguistics and math classes, and that’s it. And I want to take two difficult, interesting classes at a time, so I don’t have to juggle intro to voice bullshit while I’m actually learning.
Or if I don’t go back to school, I don’t think I want to be a game programmer anymore. Certainly not a $6,000,000 game programmer anymore, but perhaps not one at all. Games are not interested in correctness; all they care about is “working”. But I care a lot about correctness. I get off on solving problems completely, not mostly. I think I want to work in compilers. Compilers really care about correctness, and I think that’s why I really like them. If you add an optimization to a compiler, you’d better be damn sure that the optimized code is always equivalent to the original code, otherwise you throw out your optimization.
One thing I am really getting satisfaction from right now is music. I love my improv band. I want to practice with them three days a week and then go improvising around Boulder. I’m getting a lot better at my instrument, especially when Charlie isn’t there (I think that’s my biggest problem with Charlie in this band; it’s not that he isn’t adding to the music, it’s that I don’t have to work as hard when he’s around, so my technique is not improving). Another path I think I would be content with is to stop working and stop school, and go music full-on. There is, of course, the money problem if I go that route.
But something else has changed in 2007, and I’m beginning to think that it has had a big impact. My relationship with Karlin changed from “soul mate” to “good friend”. I can no longer think of her as someone who will always be there for me. The stuffed poodle she gave me in 2001 isn’t working anymore, it’s just a stuffed animal now. I’m getting lonely.
A friend of Namaste and mine, Jenn, came over last night. The three of us went for a long walk and sat in the grass and talked and all that good stuff. But that reminded me that I need somebody to cuddle with; it was really hard to restrain myself from touching her hand or something. Yes, she’s quite beautiful, but I’m not usually tempted so (like Jude :-). I think that’s reflecting more of my emotional state at the moment than any particular attraction towards her. (Well, that’s not entirely true. I could write a whole post about the subtleties and complexities of that bear. But I’ll save that for another time, probably never.)
I get the feeling that this is an inflection point in my life, and that the changes in January and February were just the beginning. I keep thinking that August is the pivot, where I will make the decision about what to do next. But experience has shown me that when such tension starts building for something to change, it manifests itself much more quickly than we plan. If I start feeling like I’m eventually going to have to quit NetDevil, I wouldn’t be surprised if I got fired tomorrow.
Evan and I played with a new drummer, Kevin Masse, last night. It was just the three of us: keyboard, bass, and drums. It’s something I’ve wanted to try for a long time. I’ve always been interested in whether I had the chops to keep a trio together. I think the conclusion is that I do, but I function in a quartet better, where I have time and space to sit out and just listen. I think as I improve more, the trio thing might get more and more viable.
In any case, here are the recordings:
Gamedev is having a board game contest next Tuesday. This had me excited enough to come up with a new board game, before the contest (so I can’t use it for the contest, because you’re supposed to come up with one on the spot!). The constraints for the contest are: has to be played on a Go board with Go stones, and cannot have more than 5 rules (which is tough to measure, but essentially it should be simple). It’s an exercise in emergent complexity.
When you think about a grid and emergent complexity, what comes to mind? That’s right, Conway’s Life. Here’s my board game based on it:
The initial board state is two π heptominos, facing each other and offset by one, like so:
---- x x x x xxx ooo o o o o ----
Don’t let the picture fool you, the board is bigger than that. I think 19 (standard Go board) is a good width. “o” can also go past the line at its back, but if “x” makes it there, then “x” wins (and vice versa, of couse).
On each player’s turn, he may add or remove a white or black piece (there is no restriction that the white player may only add or remove white pieces) according to the rules of Conway’s life:
- If an existing stone has fewer than two or more than three similarly colored neighbors, it may be removed.
- If an empty space has exactly three similarly-colored neighbors, then a stone of the same color may be added.
- If a piece has exactly three oppositely-colored neighbors, then it may be replaced by the opposite color, and it is considered to be “captured”. For example, if you had a board like this:
Then an “o” may be placed (by either player, but it’s obvious who would want to do it) and replace the left “x”, which gives the “o” player a capture. If this is done 5 times, then the “o” player wins.
Winning conditions are twofold: if you reach the opposite edge of the board (which we’ll say is the farthest point of the initial setup (the dashed lines in the first example)), then you win. Or if you succeed in capturing five pieces, you win.
And, the killer sixth rule which is a necessity: the ko rule. The board may never return to a previous state.
I was originally going to call it Conway’s God, because it’s life that you are “playing god” over. But Jude asked what we were playing, and Namaste said “Life, one step at a time”, so that is the official name now :-). It can be shortened to Losat if you wish.
At work I’ve had the pleasure of programming a preprocessor for our code base. It just takes an XML specification of structures and generates Lua accessors, serializers, etc. I did it in Python, mostly because our developers already have to have Python installed to use the test suite. This has given me a chance to get more familiar with Python as a programming language for doing real things (previously I knew enough to make minor modifications to code; basic block syntax, variable model).
First, I love the “usual” syntax. That is, as long as you’re doing fairly straightforward things, the syntax is beautiful, readable, and clean. I don’t mind the common complaint that variable declaration is implicit with assignment (I also don’t mind having a short declarator, either; as long as it catches name typos, I’m happy). I was happy to learn that Python had real closures via nested function definitions. Previously I believed that it did not support closures, which is why I did not port Glop to Python.
I think Python excels where other languages are mediocre is in communicating to the compiler and the user simultaneously, clearly, what is going on. The language layout essentially enforces that with statement-only assignment, indentation interpretation, and an overall choice of function names over syntactic constructs; it’s difficult to write code that looks like it’s doing something different than it is.
However, that strength of Python is also a weakness. After enough abstraction and indirection, you want to be communicating different things to the computer and to the user. If you communicated to the user what you communicate to the computer, you will just confuse the heck out of the user. At this level, I want a language which allows me to communicate precisely to the compiler, while communicating a good way to think about the code to the user. I would never be able to write a Language::AttributeGrammar for Python, simply because the level of abstraction in that module is too high. It takes a lot of my brainpower to think about its control flow path (driven by thunk evaluation), and if I were forced to communicate that path to the user, my module would be useless.
I think one of the biggest reasons why it is not possible to express code at this level is the lack of a multi-statement lambda. It seems like whether lambda is single-statement or multi-statement is irrelevant, since you can do the equivalent of a multi-statement lambda by using a nested function and naming the codeblock. However, it scatters around the control flow when it should be linear (or when it should look like it’s linear when it’s actually not). It also forces the user to think about functions and the concept of passing functions (which many programmers are not comfortable with), when it could just look like another block construct.
For example, I wrote a function which atomizes output; i.e. do a whole bunch of output operations in sequence, and if an exception is thrown at any time during the process, then nothing is output. This was important because I was using exceptions to communicate when an accessor couldn’t be generated, and I didn’t want my program to write the accessor declaration and opening brace if I couldn’t put something inside.
My use case code could look like this (using Ruby-style parenless block passing):
atomicio(handle) lambda handle: handle.write("foo") if blah: raise Exception, "baz" handle.write("bar")
The idea is that if blah ended up being true, then neither “foo” nor “bar” would be written. This abstraction has been important for the clarity of my script. Instead, it looks like this:
def writeFooBar(handle): handle.write("foo") if blah: raise Exception, "baz" handle.write("bar") atomicio(handle, writeFooBar)
Okay, that’s not that bad, but your eyes jump around a bit more as you’re reading this. First you skip past the def because it’s a def, then you read the atomicio line and notice that it’s passing the writeFooBar function, so you scan for the function and find it above you. It doesn’t read like a book, it reads like an academic paper :-).
It gets worse when you want composability, though. Say I wanted to do atomic I/O on two handles at once:
atomicio(fh1) lambda fh1: atomicio(fh2) lambda fh2: ...
As opposed to:
def writeFooBar(fh1): def writeFooBarHelper(fh2): ... atomicio(fh2, writeFooBarHelper) atomicio(fh1, writeFooBar)
Now do you see the difference? The structure of the first example is pretty obvious, but the second example is significantly more awkward. writeFooBar logically takes two arguments, but that clarity has been lost by the explicit currying. Additionally, the order ends up appearing backwards in the source file (fh2 before fh1).
Of course, I don’t think this is something that should be fixed in Python. If Python decided to abandon its very explicit vision of being clear about what you’re telling the compiler, it would fail at being a more expressive language. The languages that really excel at this kind of thing are Perl, because you can play syntactic tricks on the Programmer’s eyes, and Haskell, because the entire language is designed around functional abstraction (a Monad, for example, is just an extension of the idea I presented here). Python would have to change too much to compete with them, and it would almost certainly lose every value it has that puts it in front of other languages.
My improv band seems to be falling apart, mostly driven by my inability to find a drummer to substitute for Phil. I get the feeling that Evan and Charlie want to keep it going, but it’s been idle for too long and we’re all aching to play music. Charlie is okay with having a drumless band, but I’m not (I’m not averse to practicing without a drummer, but I want a drummer for the long term vision).
I wonder what the best plan of action is. Should I get the three of us together just to tighten our group and keep it going? Maybe I should invite Evan and a drummer for a jam session, and try to form a core out of those three. Then I could add Charlie soon, when we found that the three of us are not enough to hold it together. That way the drummer does not feel like he’s coming into an existing project, and hopefully he can become a reliable core member. Then we have two cores, Evan+Luke+Charlie and Evan+Luke+drummer, and we could merge to form a tight group.
I’d also like to experiment playing with some completely other groups of improv musicians. I recognize that what we’ve done has been unique and pretty cool, but I’d like to explore the space a bit more. I don’t think Evan and Charlie are a perfect match for me (but imperfection may be a virtue, keeping new and conflicting ideas flowing, so we stay versatile).
It looks like my current plan is to start over on craigslist, calling all musicians, and then keep Evan and Charlie in the book for that.