"What is it" vs. "What does it do" vs. "Just do it"

On the Objective-C mailing list, Patrick Collins asked the following:

I am wondering, what is the difference between testing if an instance responds to a method, and checking the kind of class it is?

I mean, I understand that if you had 10 classes that all have a method, and one that doesn't, it's easier to just do [myClass respondsToSelector:@selector(foo)], rather than doing [myClass isKindOfClass:[Thing1ThatHasMethod class]] || [myClass isKindOfClass:[Thing2ThatHasMethod class]] || …etc

But, I have a situation where an NSDictionary is holding an object that is either an NSNumber or an NSArray of NSNumbers.. And I wondered which of these is the best way to go?

  if ([item isKindOfClass:[NSArray class]])

vs.

  if ([item respondsToSelector@selector(objectAtIndex:)])

?

Here's my personal roundup of how I use the approaches that were discussed in response to Patrick's question.

isKindOfClass:

I would use isKindOfClass: for the situation Patrick (the OP) described. You already have specific expectations that the dictionary entry will be either a number or an array (assuming your data isn't corrupted). You want to know which it is, so you ask it. To me, this maps most closely to my mental model of the situation.

One scenario where I've used isKindOfClass: is when getting values from NSUserDefaults. I may have changed the app from allowing just one value for a user preference to multiple values, so I could reasonably expect to get either an NSNumber or an NSArray.

respondsToSelector:

I typically use respondsToSelector: in these scenarios:

  1. I'm deciding whether to send a particular delegate message to my delegate, and there's no hint in the declaration of the delegate that lets me assume it implements the method. For example, the delegate might be declared as a plain id, so I have no idea at all what it implements. Or it might be declared as conforming to a delegate protocol, but that particular method might be @optional. Note that I'm in this scenario when I'm creating the class that does the delegating — that's the class that has to decide whether to send the message.

  2. Occasionally in an action method I'll sanity-check the "sender" argument. I may be expecting the sender to respond to -representedObject (and not caring whether it's because it's an NSMenuItem or an NSButtonCell or whatever), so I check for that.

  3. Occasionally I do something similar to the responder chain where I look for an object on some chain that responds to the message, and if I find one, I send the message.

In all these scenarios the question is "I have this message I might want to send, and I want to know whether and to what object I should send it."

conformsToProtocol:

I don't think I've ever used conformsToProtocol:. I don't have a cogent explanation for why not. It's just never seemed to be the real question I wanted to ask.

Category methods

By adding category methods, you can let the inheritance mechanism do the "if this kind of object, then do that", which is after all what it's designed for. Ondra ÄŒada gave an example:

@interface NSObject (MySum)
-(int)mySum;
@end
...
@implementation NSNumber (MySum)
-(int)mySum { return self.intValue; }
@end
@implementation NSObject (MySum)
-(int)mySum { int s=0; for (id o in self.objectEnumerator) s+=[o mySum]; return s; }
@end

Mike Ash gave a variation which is the logical equivalent of isKindOfClass: in this special case:

@interface NSObject (FooChecking)
- (BOOL)ma_isFoo; // prefixed to avoid conflict
@end
 
@implementation NSObject (FooChecking)
- (BOOL)ma_isFoo { return NO; }
@end
@implementation Foo (FooChecking)
- (BOOL)ma_isFoo { return YES; }
@end

Smalltalk takes a similar approach with methods like isNumber and isSymbol, which every Smalltalk object responds to.

I like the category approach and have used it on occasion, especially where (a) I'm doing the check in a lot of places, and/or (b) I feel it expresses my question better. I am lazy enough that I'll just do an isKindOfClass: if it's only in one place.

Even with the isFoo approach you'll probably be casting to Foo* at some point, so you're still "cheating" in that you're using knowledge of an object's specific class.

The shi-shi-shi poem

Byron Han shared this article [1] by Jian Shuo Wang about a Chinese poem written in 1930 in which every word is "shi" [2].

Here's the text of the poem:

石室诗士施氏,嗜食狮,誓食十狮。适施氏时时适市视狮。十时,适十狮适市。是时,适施氏适市。氏视是十狮,恃矢势,使是十狮逝世。氏拾是十狮尸,适石室。石室湿,氏使侍拭石室。石室拭,氏始试食是十狮尸。食时,始识是十狮尸,实十石狮尸。试释是事。

I selected this text and told my Mac to "Start Speaking". For some reason in my System Preferences I had the "Kyoko" voice selected at the slowest speed, so it came out sounding like a drunk Japanese woman.


I changed to the "Ting-Ting" voice at normal speed and heard it in mainland Chinese as intended. Fun!


In Cantonese (the "Sin-Ji" voice) the words are not only different from Mandarin but much more different from each other than in Mandarin. In Cantonese most of the syllables are "see", a few are "sik", quite a few are different altogether. This did not surprise me.


What did surprise me was how it came out in the Taiwanese voice ("Ya-Ling"). I had thought mainland and Taiwanese Mandarin were pronounced the same word for word, with the only difference being a matter of accent, the way Minnesotans pronounce harder R's than Californians. But it turns out there are some words that are pronounced completely differently.


Wang gives a translation of the poem in his blog post. Rather than copy it here, I suggest you visit his blog at the link I gave. I like what Google Translate returns, especially the phrase "relies on the vector potential":

The sarcophagus poetry Guests Amur, addicted to food lion, oath eat ten lions. Suitable Amur always suitable for the city, as the lion.Ten o'clock, fitness, fitness ten lions. Yes, the appropriate Amur appropriate city. 's Depending on those ten lions, relies on the vector potential, so that the death of ten lions. S pick the ten lions corpse, fitness sarcophagus. Shishi wet, that's so paternity swab sarcophagus. The sarcophagus the swab,'s start tasting is ten lions corpse. Food before consensus is ten lions corpse, the real ten lions corpse. Interpreting things.

I used the Mac's "say -o" command to generate the above audio files. The output was in AIFF format, which I converted to MP3 using an app called "Music Converter".

UPDATE 1: Edited to mention Jian Shuo Wang by name, and to mention that he offers his own translation of the poem.

UPDATE 2: It occurred to me that a person claiming to be a native Mandarin speaker could be tested by being made to read this poem aloud. In theory a real native speaker would have less trouble getting the tones right than a faker, making this poem — dare I say — a sort of "shi-bboleth".


[1] Actually Byron linked to an article on Shanghaiist.com, but I'm linking here to the original article which it links to.

[2] Note that "shi" is not pronounced "shee" as you might think. It's more like the English word "shirr". It amuses me that the word "是" by itself, which means "Yes" or "Okay," sounds like "Sure." It's an affirmative answer in two languages.

Minor fixes to Speech voices

This is an update regarding my post about the international speech-to-text options on the Mac — specifically, about the text fragments they use for the "speakers" to introduce themselves.

The text fragment used by the Cantonese Sin-Ji voice still contains the name "Sin-Ji" in Romanized form, but somehow when it's pronounced it sounds more like Cantonese than before.

Here's the text fragment that gets spoken:

$ plutil -convert xml1 /System/Library/Speech/Voices/Sin-Ji.SpeechVoice/Contents/Info.plist  -o - | grep -A 1 VoiceDemoText
 
<key>VoiceDemoText</key>
<string>您好,我叫 Sin-Ji。我講廣東話。</string>

Here's how it used to sound:


Here's how it now sounds:


I wonder how it does that — how the text-to-speech engine can possibly know the right tones to use for "Sin-Ji", or even that it's a Chinese name. Regardless, I wish they'd use the Chinese characters for the name because I'd like to know what they are.

The text fragment used by the Taiwanese Ya-Ling voice does what I want. It has replaced the Romanized "Ya-Ling" with Chinese characters.

Here's the new text fragment ("Ya-Ling" has been replaced with "雅玲"):

$ plutil -convert xml1 /System/Library/Speech/Voices/Ya-Ling.SpeechVoice/Contents/Info.plist  -o - | grep -A 1 VoiceDemoText
 
<key>VoiceDemoText</key>
<string>您好,我叫 雅玲。我說國語。</string>

Here's how it used to sound — pretty disastrous:


Here's how it now sounds — note how different the "Ya-Ling" is:


You can hear these voices yourself by going to System Preferences > Dictation & Speech > Text to Speech. If you don't already have the voices for these languages installed, it'll take a while to download them.

I'm on 10.8.2. I don't know when Apple made these changes.

East Bay Vivarium

Last week while in Berkeley I came across a reptile store called East Bay Vivarium. I wanted to stay all day.

Here are two huge snakes they had:

ssssnake
[Credit: kittyfisher on Flickr]

asleep
[Credit: dotpolka on Flickr]

Coiled up like this, they were each about the size of an automobile tire.

There are more great photos on the store's web site and Facebook page.

There was something intimate about viewing these creatures this way that I liked better in some ways than any zoo or aquarium.

Thanks to Google Maps, you can look around inside the store without being there.


View Larger Map

$1 apartments — NOT

I hate when apartment brokers list $1 rents on Craigslist so they will always show up in searches. The problem is worse in some neighborhoods than others (at least in NYC). In the Financial District, these misleading listings drown out the listings that show only actual rent amounts.

It looks like the brokers who do this often deal in fairly pricey apartments, so it seems silly, not to mention spammish, to try to grab the attention of people seeking cheap rents.

One dollar rent

This morning I realized it's easy to avoid those listings: just set the minimum rent to $2 instead of leaving it blank. Sure, it's obvious now, but this wouldn't be the first time I was slow on the uptake.

Speaking of slow uptakes: when I first started searching for apartments on Craigslist, it took me a while to figure out why there is a minimum-rent field at all. Who wouldn't want to pay as little as possible?

One reason is that you might figure you get what you pay for, and you don't want your search results cluttered with the cheap stuff.

Another reason is so that you can omit listings you've already looked at. For example, if you don't like any of the apartments under $1000 and might consider bumping your budget up to $1100, you'd search on the range $1000-$1100, because you don't need to see the under-$1000 listings again. (I picked $1000 because it's a nice round number, not because it'd get more than a broom closet in NYC.)

And now I see a third reason: to avoid seeing the bogus $1 listings.