Wednesday, October 26, 2005

Your iPod is Too Old

I just updated my installed version of iTunes. I went from 4-something to 6-something. When I synced to grab the couple of songs I just bought, I got a message that went like: "Not all of your songs could be synced because the software on your iPod is too old." Okay, fine, I haven't updated my firmware in a year . . . so I go and pull the latest update. Install it. Reboot. (Grrr!)

Then I re-sync it, to see what it was that couldn't be synced. Lo and behold, the answer is: everything I've ever bought from iTunes! I don't know for sure, but I'm guessing (and I'm confident it's a good guess) that they updated their DRM to combat whatever evil scheme the hackers have concocted to crack it.

This freaked me out a little. Hello, dumbasses at Apple! This is EXACTLY what the general populace hates and fears about DRM -- that even though they have bought something, they don't really "own" it, and the provider can revoke their access to it on a whim. This is the sort of thing that drives people to allofmp3.com. It's not too much to ask that I can keep the things I've rightfully paid for, is it?

Sheesh. For $.99, I'd be happy to sell you guys a clue.

Friday, October 21, 2005

WHAT on WHAT?

Just got back from taking my kids to see Disney on Ice at the HP Pavilion. It was okay, kinda fun, though clearly I am not in their target demographic. The Tarzan section of the show had a couple of mind-bogglingly awesome moments in it, the rest I was about 30 years too old for.

The high point of the evening for me was afterward, I was carrying my son back to the car because he was exhausted. "Aidan," I said, "it's a good thing you're light, otherwise I don't think I could have carried you all this way."
"I'm strong though," he said. "I could break your finger. Wanna see?"
Then, while I attempted to get his seatbelt buckled, he kept trying to grab my finger so he could prove that he was strong enough to break it. It took five minutes to get him strapped in, and the whole time we were in hysterics.
I, too, am tired :-)

Saturday, October 15, 2005

More updatey goodness

Again, for the six people who ever see this, I have added a custom style to the stock blogger.com template that fixes up images so they don't blow out the new template's post column. As a bonus, it will work automagically for any pictures I might add in the future. (And I do have a few, I have just been lazy about pulling them off my camera and adding them. Shocking, I know.) Anytime the pic is bigger than the main post column, I link directly to the pic, so click it to see the bigger version. If it's not linked, that's as big as it gets.

If you want to read this damn thing but are sick of how infrequently it's updated, may I recommend Bloglines, or Feed Demon? I'm told Firefox's live bookmarks feature is quite nice, as well, though I haven't taken the time to figure out how it works yet.

A face only a programmer could love

I need to get back in the swing of updating this regularly, and my threatened article on generators in Python seems like as good a topic as any. I use a generator maybe every other month, and each time I have to do it wrong once and then remember how to do it correctly. So I figured I would document my experience here, so the next time I have to do this, I can refer back and hopefully save myself some time. Oh, and you guys can read it, as well.

Generators in Python are odd ducks. They feel like a giant hack to me. I want them to be functors, but they're not. In fact they are syntactic sugar for creating an iterable object. Consider the following (which, in fact, is an iterable functor):
RED = "FF0000"
WHITE = "FFFFFF"

class Iterable:
__color = WHITE

def __call__(self):
if self.__color == RED:
self.__color = WHITE
else:
self.__color = RED
return self.__color

I = Iterable()
print I()
print I()
print I()
The output I get from this is:

FFFFFF
FF0000
FFFFFF

This is something I might do anytime I need to generate a pattern or a sequence. Obviously this is a very simple example, but there's plenty of room for complexity here.

Generators let you do this (arguably) in a simpler, cleaner fashion:
RED = "FF0000"
WHITE = "FFFFFF"

def generator():
color = RED
while True:
if color == RED:
color = WHITE
else:
color = RED
yield color

I = generator()
print I.next()
print I.next()
print I.next()
This gives the same output.

What I want to do is call the generator function repeatedly. In fact, calling the function creates the generator. The body of the function gets grafted onto the new generator object, where it acts kind of like a coroutine: the function's execution is suspended at the yield statement, and resumes after the yield the next time next() is called.

Of course, this example doesn't really demonstrate the real value of a generator over a hand-crafted iterator class. Consider this:
for x in range(3):
print '<tr>'
for y, color in zip(range(3), I):
print ' <td bgcolor=%s>&nbsp;</td>' % color
print '</tr>'
Which results in this chunk of html:
<tr>
<td bgcolor=FFFFFF>&nbsp;</td>
<td bgcolor=FF0000>&nbsp;</td>
<td bgcolor=FFFFFF>&nbsp;</td>
</tr>
<tr>
<td bgcolor=FF0000>&nbsp;</td>
<td bgcolor=FFFFFF>&nbsp;</td>
<td bgcolor=FF0000>&nbsp;</td>
</tr>
<tr>
<td bgcolor=FFFFFF>&nbsp;</td>
<td bgcolor=FF0000>&nbsp;</td>
<td bgcolor=FFFFFF>&nbsp;</td>
</tr>
Giving us our lovely checkerboard pattern. What the generator gets you is automatic conformity to the iterator interface (namely, the next() function, and having it raise StopIteration if it runs out of values to return). When you write a custom iterator class, you have to do these things yourself (otherwise, your iterator may not conform to the expected interface, and may break when you reuse it down the road).

Thursday, October 06, 2005

Wow, that was five fast months

A couple of quick ones, just as an excuse for updating this:

Blogger.com has new templates, and so I am now using a non-sucky one. The three people who actually ever read this thing, rejoice!

New in the "top ten reasons working for EA is good": we now have a dodgeball league :-)