言語女子会: undefとnullは両方必要?

Twitterのタイムラインが面白すぎて、ついうっかり言語を擬人化して脳内で言語女子会なるものを開いてしまいました。なお、登場人物と実在の人物は1対1に対応しません。

undefinedとnullの両方必要なの?

とあるプログラミング言語が集う女子会にて:

Perl: そういえばさ、なんでJavaScriptちゃんってundefinedとnullの両方もってるの?
JavaScript: えっ、未定義の変数にアクセスした時undefined返したいじゃない?
Python: 例外投げて死ねばいいじゃん
Ruby: 例外投げて死ねばいいよね
Python & Ruby: ねー♡
Java: いやそこは参照型ならnull、数値型なら0で初期化すべきでしょ
C: これだから最近の若い子は…初期化にだってコストが掛かるんだからね!デフォルトで初期化するなんて無駄遣いよ!必要な人だけが責任をもって初期化すべきなのよ!
Perl: (Cおばさん怖い… Javaさんもなんか型苦しいし…) でもね、仮に初期化するとして、nullかundefかどっちか片方あればいいでしょ?
Lisp: (あらあら それを言うなら nil と 空リスト も 片方でいいでしょ (と 思ったが 言葉には しない) そっと #t を 飲む)
JavaScript: うーん、そうかなぁ。今彼氏がいないのと、生まれてからずっと彼氏がいないのは別じゃない?

空リストからpopしたら?

JavaScript: 例えばさ、空のリストからpopした時ってundefined返したいじゃない?
Python: 例外投げて死ねばいいよね、Rubyちゃん
Ruby: え?nilを返すでしょ常識的に考えて
Python: は?じゃあnilの入っていたリストからpopした場合とどうやって区別するの?
C: これだから最近の若い子は…私は成功した時に0 <= n < 256の値を返す関数でも、失敗した時に-1を返すためだけにint型にしているというのに!まったく考えなしのゆとりなんだから!
Ruby: (Cおばさん、めんどくさっ) Lispさんはどう思いますか?
Lisp: (あらあら そんな昔のこと 忘れたわ (と gosh を 起動して 試してみる)) (car ()) は 例外を投げる ようね*1

存在しないキーへのアクセス

JavaScript: あとオブジェクトに指定したキーがないときもundefinedを返したいの
Python: 例外投げて死ねばいいのに。私だったらobj.has_key(k)でチェックできるようにするなぁ *2 *3
JavaScript: 今はそんな感じのことも出来るんだけど、たしか昔はできなくて…
Python: さっさと例外投げて死ねばいいのにねー、ね、Rubyちゃん
Ruby: nilを返すけどなにか文句ある?*4
Memcached: (私はfalseを返すけどなぁ、と思っているが、言語じゃないので話の輪に入れない)*5
Python: ふーん、で元からnilが入っている場合にはどうするの?(ニヤニヤ)
Ruby: (-_-#)
Haskell: いまさらundefinedとかnullとかでフラストレーション溜めてるおばさんたちはモナド使った方がいいにゅ
JavaScript: Haskellがブラウザで動くようになったら使うかもね、Maybeね
Python: その可能性はNothingね*6
Haskell: …(-_-)

まとめ

Python: でもま、CさんやHaskellちゃんの言うとおり、返り値でエラーを伝える場合、それは成功した時に返されうる値以外でなきゃダメよねー、成功したのか失敗したのかわかんなくなっちゃうもんねー(とニヤニヤしながらRubyの顔を見る)
Haskell: (賛成してもらえてとても嬉しいのだが、その感情はIOモナドに押し込められて無表情)
Python: そういう意味で、リストや属性に入れられるnullと、失敗を伝えるための無効値undefinedを区別するのは合理的ね。JavaScriptちゃんもいいところあるのよね
JavaScript: あれ、いい忘れたけどundefinedはリストに入れられるよ
Python: はぁ?!死ねばいいのに!!

あとがき

PerlPythonRubyをDISりはじめたあたりから、思い当たるフシがありすぎて心の中が$_=~#(;_;)#;#$@#{$#}...

このSSを書くインスピレーションを与えてくれた皆さんにthanks! @__gfx__ @kazuho @__kan @tanakh

興味を持った方には僕の書いた「言語設計の基礎知識」を含む60冊分のPDFが1冊にまとまったWebDB Press 総集編がオススメ:

補足

僕の発案だという勘違いがあるみたいなので引用しておきます。女子会になった理由はコレを「彼女」ではなく「彼氏」にしたかったからでした! https://twitter.com/#!/__kan/status/180580941335502848

@__kan: nullとundefinedの両方が存在してる理由が分からないっていうけど、今彼女が居ないのと生まれてこのかた彼女がいないのは明確に区別するべきでしょう

あとはこれを読んでMaybe→Nothingというオチを思いついたことも書く動機になりました笑 https://twitter.com/#!/tanakh/status/180593265706414080

@tanakh: 今更nullとかundefinedとかにフラストレーション貯めてる人はHaskel使ったほうがいいよ

反応まとめ

  • アセンブラばあちゃん「変数が定義出来るといろいろ大変なんだねえ」 (by @raitu thanks!)
  • アセンブリ言語ばあちゃん「未定義だぁ?NULLだぁ?そんなの持ってたって爺さんのフラグは立たんよ」(by id:yappo thanks!)
  • 建前は、ES5の仕様書では、4.3.9および4.3.11、「変数に値が割り振られていない時の値」「オブジェクト値が存在しないことを意図的に表現したい時の値」だよ(by @yukoba thanks!)
  • Clojureではnilと空リストは区別される。つまりClojureでは (pop '()) と (pop nil) は別物。(空リストは例外を発生させるが、nilnilをpopする) (by @omasanori thanks!)
  • 「JS の undefined の一番残念なところは、それがただのグローバル変数であることだ。」 (by @tnacigam thanks!)
  • PHPがハブられてるとことかリアルに女の人の集まりみたいで嫌だwwwwww (by id:Retrorocket thanks!)
  • PHP:(言語じゃないので話の輪に入れない) (by id:koyhoge thanks!)
  • SQLではnullがundefの意味になっててバグの温床になってるよなぁ。 (car ())はschemeではエラー、clispではnilなのか。再起終わるかはcdrで判定するから気づかなんだ。(by @Tomokatz thanks!)
  • Luanil と未定義を言語仕様上区別してない。(by @torus thanks!)

*1:by @ser1zw 「Common LispだとNILが返ってきますね(CLISPで確認)」thanks!

*2:PythonRubyは辞書・ハッシュへのアクセスの話。obj.fooでアクセスした場合はRubyでもNoMethodErrorが投げられる

*3:by @a_yasui 「(has_keyは)2.6から非推奨、3.0 からは使えないかと。代わりに in を使いませう」thanks!

*4:by @niku_name 「ちなみに hash.fetch を使うと存在しないキーへのアクセスはPythonちゃんと同じような感じになります(例外を投げる) http://rurema.clear-code.com/1.9.3/method/Hash/i/fetch.html」thanks!

*5:by @methane 「Memcachedがfalseを返すと言っていたのは、phpのクライアントの話で、ミドルウェアとしてのmemcachedはそもそもバイト列を格納するだけなのでfalseも0もnullも無いです。」thanks!

*6:Haskellでは失敗するかもしれないことを表現するための型を構築するためにMaybeモナドという型クラスがあり、その失敗した時の型がNothing