journal for 2004-04-28

food and exercise

I got out and did a good bit of cycling, today, which felt good. I ate too much dinner, though. I kept eating after I was full, which was dumb. Then again, the roast chicken we got was pretty excellent. We also had some lousy au gratin (it looked good in the case!) and some of those new rolled up doritos. Here’s the scoop on them: they’re like doritos, only rolled up.

gloria’s ibook

Gloria’s iBook decided to be a jerk today. At my urging, she installed today’s software updates. Upon rebooting, it just didn’t do anything. A verbose boot showed that the mach kernel couldn’t load. This was bad.

Apple Care was home for the day, and Google had no answers. Dan suggested I do an upgrade install from the Panther CDs, which wasn’t quite possible. Instead, I did a “archive and install,” which duped her System folder and installed a new one. Sure, it took another hour to let the Software Updates run, but it worked. Irksome. There must’ve been a better course of action in there.

Today’s iTunes updates are neat, but basically affect me in no way. I don’t see myself using any of the new features. Well, OK, I did watch one or two videos this afternoon.


Looking at my lame todo list, I found that due to the order of the letters in the Roman alphabet, Lingua::EO was next on my list. I’ve done a bunch of work on Games::Board—which I’ll get to later—so I thought I’d do a bit of work on this.

The point of Lingua::Esperanto is, eventually, to translate Esperanto to English. I’m not looking to translate full sentences, just words. For example, I want to break down “malsanulejo” into “mal-san/a-ul-ej-o” and from there into “place of not healthy people.” Presumably there would be an exception, someday, to catch this and call it a hospital. Still, this would be useful even without that. It would certainly help me overcome my stupid problems with -igi- versus -igxi- and other silliness.

So, I started looking for Lingua modules, just to see what the namespace was like, and I found a few things that were scary, a few that were interesting, and a few that were both. The most relevant thing looked to be Lingua::Stem, which seems to be designed to turn a declined word into a stem word. I need to reread the docs, but it seemed like the author assumed that everyone knows what a stemmer does. He doesn’t have any concrete “word in, word out” examples or other solid demonstrations. Still, I think I’m making a safe assumption.

I saw another stemmer, and I think that unless I want to use the Ligua::Stem API (which I don’t think I do, just yet), Lingua::EO::Stemmer, or something like it, will be born.

Seeing a bunch of stemmers for different languages, I moved on to search for Esperanto modules, guessing I might find something useful. I didn’t, really. I saw that Jouke had a bit of code to transcode Esperanto text, fixing h-coding and x-coding. Other than that, I didn’t see much related to Esperanto. I did see this, though: Lingua::Num2Word. It has the (maybe) noble goal of uniting all the number-to-prose modules through one tolerable interface. It has the (unquestionably) failing of being needlessly OO. The constructor is a vanilla bless of an empty hashref, and the methods never use the implementation object. Actually, the code is more complicated because it needs to decide whether or not it’s being called as a function or method. (The interface is polymorphic!) In fact, have a look at its C<cardinal> method. If it’s being called as a function, it creates a new Lingua::Num2Word object in the lexical scope, does nothing with it, and discards it at the end of the subroutine. Wuh!

So, looking at that drove me to look at some of the other Lingua modules for turning numbers into strings. It’s a real hodgepodge. I’d like to find out how well-used Lingua::EN::Numbers is, as it would be nice to replace it with something both simpler and more comprehensive.

And not OO.

Of course, either way, I’ll need to write a Lingua::EO::Numbers. I think I’ll do that before the stemmer. I don’t know whether to write an EO number module as a model for EN or the reverse. Or maybe I should stay the hell away from EN number modules. I don’t, after all, feel like descending on the problem en masse like DateTime.


Two weeks ago, I said I was going to be brave and adopt another practise from XP: I wasn’t going to carry over today’s work to tomorrow. I didn’t get all my tasks done, so I released my checkout and deleted the sandbox.

“It’ll be easy,” I thought, “since the ideas are so fresh in my mind!” Well, I’m sure that would have been the case if I had actually done work on it the next day. Or any of the following ten. Instead, I did … heck, I don’t know what I did. I didn’t work on Games::Board.

I’d be honest and say that I lost all momentum, but I didn’t. The day after erasing my code, it was all fresh in my mind, and I realized the simplest way to do what I wanted to do. Sure, I should have implemented it sooner, but I had a life to live. Anyway, I finally made the determination to get some work done, and so I did.

The target I’d missed was a Games::Board::Grid that I could subclass to a chessboard that used idiomatic space identifiers. I wanted to be able to call the bottom left space ‘a1’ and not [1,1]. In the end, the problem was me being too clever. Games::Board stores spaces in a hash, keyed to id. I wanted to make Games::Board::Grid store things in a LOL, using the two-dimensional structure to represent a two-dimensional grid. “Ho ho,” I thought, “Perl is powerful because I can implement a subclass as a different reference type!”

Yeah, well, that’s dandy, but stupid. I wasn’t getting any benefit from having each row in its own array. I wasn’t doing anything neat with the LOL. It was dumb. Then, I ended up having routines that once compared strings trying to compare arrayrefs. Then I had to not trample on passed reference values. Then I had another layer of indirection by which idiomatic identifers were being replaced with arrayrefs. That is, ‘a1’ had to become [0,0].

See, the thing I remembered on The Day After was that I should have looked for the simplest thing that would possibly work. Being too clever is great for cocktail parties, but not so much for coding. I just put in one layer of indirection: when needed, identifiers can be turned into a grid position. Otherwise, they’re still strings. The board is still a hash. By default, the first allocated corner of a Grid board has the id ‘0 0’—yeah, it’s ugly, but it works fine. Writing a chess id generator was trivial, and so was go.

Inspired by my success at getting that code working, I started to refactor Games::Goban. My first mistake was to try to refactor it in place. Yanking out an internal storage mechanism and replacing it with a foreign backend while not altering the public API? It’s not rocket surgery, but it’s a lot harder when you’re writing the foreign backend while you do it. About halfway through the operation I realized that I was digging a pit, deleted everything, and watched a movie. The next day, everything was fine.

I’ve built Games::Goban::Board, which will be the internal representation of the board in Games::Goban, when its overhaul is complete. The next step is to replace Goban’s internal board manipulation with this class. It’s only weird because Goban is both a board tracker and a game tracker. Still, it shouldn’t be so complicated. It will give me a reason to implement the C<iterboard> and C<register> functions from Games::Goban into the base Games::Board class.

What I really need, next, is a way to promise myself that I’ll work on something at a given time and try to achieve a given goal. My lousy todo list is lousy, and I’m not sure what I want to do to make it better. Templates for better OmniOutlines are welcome.

Written on April 28, 2004