はじめに
近頃、null 安全とやらが流行しているようです。なんでも、null って危ないものだと思われているようです。そんな null について以前 nilは悪か?なるポエムを書きましたが、多勢に無勢、もう心が折れてしまいそうです。
こうなったらもう Smalltalk の世界にヒキコモるしかありません。そこで、Smalltalk の代表的な処理系で nil の賢さについて比較してみました。
比較する処理系
とりあえず、今元気がいい処理系として Pharo 5 と次バージョンとなるべく開発中の Pharo 6、総本山といっていい Squeak 5.1、PARC直系正統派の VisualWorks 7.10.1、そして GNU Smalltalk 3.2.5 を比較してみました。
nilのクラスが定義しているメソッド数
nilがどんなに賢いか。プログラマとしてはコードがオブジェクトを賢くすると思いたい。つまり、メソッドがいっぱい定義されていれば賢いだろうということで、nilのクラスである UndefinedObject が定義しているメソッドの数を比較してみました。次のコードで確認できます。
nil class selectors size
結果は以下の通りです。
処理系 | メソッド数 |
---|---|
Pharo5 | 62 |
Pharo6 | 57 |
GNU Smalltak 3.2.5 | 44 |
Squeak5.1 | 40 |
VisualWorks 7.10.1 | 38 |
Pharo たん、賢い!
新旧Pharoのワンツーフィニッシュです。
nilが応答できるメッセージセレクタの数
UndefinedObjectで定義されていなくてもいいじゃないか、Objectとかから継承されていてもいいじゃないか、応答できればいいんだい!というわけで、継承した分もあわせてセレクタ数を数えてみました。
nil class allSelectors size
結果は
処理系 | 応答可能セレクタ数 |
---|---|
Squeak5.1 | 511 |
Pharo6 | 476 |
Pharo5 | 468 |
VisualWorks 7.10.1 | 278 |
GNU Smalltak 3.2.5 | 157 |
さすが、Objectの分厚さでいえば Squeak ですね!
9bitの符号なし整数の最大値をマークしました。
Pharoも6が5を抜きました。
そして清く正しい GNU Smalltalk はやはり清く正しかった。
コードの中で nil 判定をしている密度
null 安全どーたらでは、nil 判定はバグの元だそうです。よくわからんけど。
というわけで、標準ライブラリ中の1メソッド当たりの nil 判定の個数を計算して、どの処理系が一番 nil 判定が多いかを見てみましょう。
コードは
(#isNil senders size +
#notNil senders size +
#ifNil: senders size +
#ifNotNil: senders size +
#ifNil:ifNotNil: senders size +
#ifNotNil:ifNil: senders size) /
(Object allSubclasses inject: 0 into: [ :sum :each | sum + each selectors size ]) asFloat
ただし、Squeak と VisualWorks と GNU Smalltalk には Symbol>>senders が定義されてないようなので、それぞれ Symbol に定義してみました。
senders
^ self systemNavigation allCallsOn: self
senders
| collector |
collector := MethodCollector new.
^ collector select: (collector referencesTo: self)
GNU Smalltalk は…ごめんなさい、どうしたもんか皆目見当もつきませんでしたわい…orz
さて、結果は…
処理系 | nil判定密度 |
---|---|
Squeak5.1 | 0.152 |
Pharo5 | 0.107 |
Pharo6 | 0.105 |
VisualWorks 7.10.1 | 0.088 |
GNU Smalltak 3.2.5 | - |
一番 nil 判定を頻繁にやっているのは Squeak 5.1 でした。VisualWorks、nil判定少ないですね。まあいずれにせよ、Smalltalk を書いたらこんぐらいの頻度で nil のことを気にしてみましょうね、ってことなのかな。よくわからないけど。まあ10個メソッドを書いて1回思い出すぐらいならオレにもできそうなので安心しました。
おわりに
どの Smalltalk の nil が賢いか比べるつもりでしたが、どうもあまり大差ないというのが率直な感想です。
差が目立ったのは allSelectors でしたが、これは nil どうこうというよりも、Squeak の Object が肥大化していて、Squeak から派生した Pharo もやっぱり Object がメタボっている、という解釈が一番ピンとくるかなあという感じで、nil の賢さとはちょっと違うような気がします。
というわけで、結論は、
Smalltalkの nil はみんな賢いから、どんどん使おう!
ということで、めでたしめでたし。
追記 (2016/12/19)
Юрий Мироненко さんによる 素敵な nil への対処法。
Protego - smart way to manage nil in business calculation