New weblog!
latest
chanson
I've finally moved my weblog to my own domain! You can find it at http://eschatologist.net/blog/ now and probably forever.

I mostly wanted to wait until both WordPress and MarsEdit supported tags well, rather than just categories, and I wanted to wait until I could figure out how to migrate things easily. The latter I never really did; any migration I do is by hand, copying out of Xjournal and pasting into MarsEdit.

I've migrated many of my posts to the new weblog so far. I'll migrate more over time, and I'll fix up the internal links over time too. In the meantime, it's nice to be able to use MarsEdit to manage my posts, and to edit them as Markdown.

So update your subscriptions and be sure to stop by!

DDJ vs. Backyard Poultry
latest
chanson
Eric Sink has a post talking about the sad state of developer publishing, specifically discussing the declining readership of the venerable developer magazine Dr. Dobb's Journal, as compared to that mainstay of American newsstands Backyard Poultry.

After reading the article and the replies, I just had to throw in my two cents about magazine publishing and why "1% of the US population are software developers, so there should be a huge market for development magazines."

It's a significant mistake to think that the reader is the target and that the magazine is the product.

It is actually the aggregate readership that is the product, and the advertisers who are the target. That is, unless the magazine takes no advertising and is entirely supported by its subscribers.

This was driven home to me recently when I bought the recent "eInk Flashing Cover" issue of Esquire. I had never read Esquire before, so in addition to checking out the cool hardware on the cover, I started trying to read it. It was way more full of ads than Wired ever was — even in the days when Suck famously disassembled Wired 3.09 to remove the ads.

Furthermore, its advertisers were all very high-end. Thus I wasn't that surprised when I saw that the price on the subscription card for a year of Esquire was well under $1/issue.

So if Dr. Dobb's Journal is circling the drain, it's not the current readership that's to be blamed, or the Internet. It's the lack of advertisers interested in reaching that readership, or the magazine's ability to reach a readership that is interesting to a better-paying tier of advertisers.

Let's merge managed object models!
latest
chanson
There was a question recently on Stack Overflow asking how to handle cross-model relationships in managed object models. Now, the poster wasn't asking about how to handle relationships across persistent stores — he was asking how to handle splitting a model up into pieces such that the pieces could be recombined.

It turns out that this is somewhat straightforward to do using Core Data. Let's say you have a simple model with Song and Artist entities. I'll write it out here in a pseudo-modeling language for ease of reading:
MusicModel = {
    Song = {
        attribute title : string;
        attribute duration : float;
        to-one-relationship artist : Artist,
            inverse : songs,
            delete-rule : nullify;
        userInfo = { };
    };

    Artist = {
        attribute name : string;
        to-many-relationship songs : Song,
            inverse : artist,
            delete-rule : cascade;
        userInfo = { };
    };
};
Now let's say you want to split this up into two models, where Song is in one and Artist is in the other. You could just try and create two xcdatamodel files in Xcode, one with each entity, and wire the relationships together after loading them and merging them with +[NSManagedObjectModel modelByMergingModels:]. Except that won't work: Relationships with no destination entity won't be compiled by the model compiler.

What else might you try? You could try just putting dummy entities in for relationships to point to. However, merging models will fail then, because NSManagedObjetModel won't merge models that have entity name collisions.

It turns out, though, that you can merge models very easily by hand, by taking advantage of the way Core Data's model-description objects handle the NSCopying protocol. All you have to do is create your destination model, loop through every entity in each of your source models, and copy every entity that you haven't tagged as a stand-in using a special key in their userInfo dictionary.

Why does this work? The trick is that before you tell a persistent store coordinator to use a model, that model is mutable and references relationship destination entities and inverse relationships by name. So you can have only a minimal representation of Artist in one model, and a minimal representation of Song in another model:
SongModel = {
    Song = {
        attribute title : string;
        attribute duration : float;
        to-one-relationship artist : Artist,
            inverse : songs,
            delete-rule : nullify;
        userInfo = { };
    };

    Artist = {
        /* Note no attributes. */
        to-many-relationship songs : Song,
            inverse : artist,
            delete-rule : cascade;
        userInfo = { IsPlaceholder = YES; };
    };
};

ArtistModel = {
    Song = {
        /* Note no attributes. */
        to-one-relationship artist : Artist,
            inverse : songs,
            delete-rule : nullify;
        userInfo = { IsPlaceholder = YES; };
    };

    Artist = {
        attribute name : string;
        to-many-relationship songs : Song,
            inverse : artist,
            delete-rule : cascade;
        userInfo = { };
    };
};
Then, when you write some code to combine them, the merged model will wind up with the full definition of Song and the full definition of Artist. Here's an example of the code you might write to do this:
- (NSManagedObjectModel *)mergeModelsReplacingDuplicates:(NSArray *)models {
    NSManagedObjectModel *mergedModel = [[[NSManagedObjectModel alloc] init] autorelease];

    // General strategy:  For each model, copy its non-placeholder entities
    // and add them to the merged model. Placeholder entities are identified
    // by a MyRealEntity key in their userInfo (which names their real entity,
    // though their mere existence is sufficient for the merging).

    NSMutableArray *mergedModelEntities = [NSMutableArray arrayWithCapacity:0];

    for (NSManagedObjectModel *model in models) {
        for (NSEntityDescription *entity in [model entities]) {
            if ([[[entity userInfo] objectForKey:@"IsPlaceholder"] boolValue]) {
                // Ignore placeholder.
            } else {
                NSEntityDescription *newEntity = [entity copy];
                [mergedModelEntities addObject:newEntity];
                [newEntity release];
            }
        }
    }

    [mergedModel setEntities:mergedModelEntities];

    return mergedModel;
}
This may seem like a bit of overhead for this simple example. The critical thing to see above is that only that which is necessary for model consistency is in the placeholder entities. Thus you only need the inverse relationship from Song to Artist in ArtistModel. Say you wanted to add a Picture entity related to the Artist entity — you don't have to add that to both models, only to ArtistModel. The benefit of this method for merging models should then be pretty apparent: It gives you the ability to make your model separable, just like your code.

Erlang on LLVM? or: Outsource your JIT!
latest
chanson
Has anyone been working on using LLVM to do just-in-time code generation for the Erlang virtual machine?

Depending on the design and structure of the Erlang virtual machine, it doesn't seem like it would be all that tough a project. And it could provide a nice performance boost for those projects that are starting to use Erlang like CouchDB and ejabberd.

For an example of what I'm talking about, there's a project called VMKit that has implemented the Java and .NET virtual machines atop LLVM with reasonable performance. Essentially, if you have a virtual machine, rather than skipping either just-in-time or static code generation entirely, or trying to do it all yourself for some specific platform on which you want to run, take a look at what you can do with LLVM and see if you can leverage its code generation instead.

Not it!
latest
chanson
I didn't write Carrie's Dots — but I did download it!

It was written by Dr. Chris Hanson, a Chris Hanson who's evidently still in the mid-South. Maybe the next time I get a chance to visit realgreendragon in Mississippi, we'll get to meet up!

LLVM terminology
latest
chanson
I thought the proper terminology was worth pointing out, since I've seen — and heard — some misuses lately.

LLVM is the Low-Level Virtual Machine and the project surrounding it.

LLVM-GCC is a compiler that uses GCC for its front-end and LLVM for its back-end.

Clang is the C language family front-end that is part of the LLVM project. It's a parser, semantic analyzer, and code generator — in other words, a compiler front-end that uses LLVM for its back-end.

The Clang Static Analyzer is what people have been trying out lately, to find subtle bugs in their and other projects. It's a great tool.

I just thought this was important to mention, because people have been referring to "LLVM" instead of "LLVM-GCC" in reference to the compiler included in Xcode 3.1, and people have been referring to "Clang" instead of "the Clang Static Analyzer" in reference to what they've been using to find bugs in their projects.

New bike! Marin Belvedere 2007
latest
chanson
I just got my first bike since junior high, and rode a bike today for the first time since high school! Many thanks to Meg for helping me pick it out and to Dan and others for listening to me ramble about what I might or might not want.

What I wound up getting was a 2007 Belvedere from Marin Bikes, in matte coal (of course). I test-rode it and it felt great, I could even shift — something I could never do in junior high or high school without losing control, damn post-shifters — and the only limit I felt with it was me!

So after accessorizing a bit, Meg and I rode home and then walked back to pick up the car. Cupertino and the South Bay in general are so bike-friendly I can tell I'm going to put a lot of miles on it just this summer, and if I get a good set of panniers there's no reason I won't be able to keep doing so into the fall and even winter.

And as tired as I am just from riding a couple miles today, it feels a hell of a lot better than contributing to the climate crisis while paying nearly $5/gallon for gasoline.

Always use notification name globals, not literal strings!
latest
chanson
What's wrong with this code?
- (void)registerForNotificationsFromTask:(NSTask *)task ( {
    [[NSNotificationCenter defaultCenter]
        addObserver:self
           selector:@selector(taskDidTerminateNotification:)
               name:@"NSTaskDidTerminateNotification"
             object:task];
}
If you didn't notice anything wrong, look again.

What's bad about this is that it's passing a string literal instead of a global variable for the notification name. The code should really look like this:
- (void)registerForNotificationsFromTask:(NSTask *)task ( {
    [[NSNotificationCenter defaultCenter]
        addObserver:self
           selector:@selector(taskDidTerminateNotification:)
               name:NSTaskDidTerminateNotification
             object:task];
}
Isn't that better? (Among other things, Xcode will offer to complete the NSTaskDidTerminateNotification global variable for you — unlike the contents of a string literal.)

This is a bug that often results from copying & pasting from documentation into code. "I need this notification, it needs to be a string, so I'll just put @"" around it." The type of a notification name is, in fact, NSString but you don't have to pass a string literal for that. Instead, pass the global variable that exists for each notification name and you're guaranteed that the right thing will happen.

If you're creating and using your own notifications, be sure to follow the Cocoa pattern and create your own global variables containing the notification name. Otherwise you're at the mercy of typos within string literals.

Update: Sanjay Samani helpfully pointed out that by constant string I meant string literal. Thanks, Sanjay! I've updated my post with this correction. (Not sure where my memory was…)

I fucking hate this city
latest
chanson
Meg rode her bike down from the hotel to Union Square to meet me for dinner, locking it up at a bike station right outside Borders.

After we walked back from dinner, we discovered it had been stolen. Right in the middle of dinner, right on the corner of fucking Union Square.

I fucking hate San Francisco. What a shit-hole of a city.

WWDC 2008
latest
chanson
The time is upon us once again — WWDC time!

As I have the past few years, I'll be in San Francisco all week, staying at the Hotel Kabuki in Japantown.

And of course, I'll be around the conference all week — especially in the labs. Come by and say hi, and I'll be happy to help with any questions you have!