Rubyの真偽値2009/07/23

なんか流行ってる?

RubyのnilCommentsAdd Star - s/.*// Rubyではif(0)はtrueルート なのかっ Cと逆だな - 独断!レビログ=偏見 2 == true が false で驚いた件- 予定は未定Blog版 bool, true and false.CommentsAdd Star - 危ないRiSKのブログ うつ期ver.

"Ruby では false または nil だけが偽で、それ以外は 0 や空文字列も含め全て真です。" が理解できていれば、特に疑問の余地は無いと思います。

irb(main):001:0> nil.to_s
=> ""
irb(main):002:0> nil.to_i
=> 0
irb(main):003:0> nil.to_a
=> []

また、#to_*系のメソッドは、レシーバをもとに指定のクラスのインスタンスを生成して返すので、戻り値の真偽がレシーバの真偽と一致しないのは、別に気にならないけどなあ。

あと、Cについては、もともと boolean は未定義で、"偽" == 0 だけが明確な定義で、"真"は"偽"でないもの全部ぐらいの定義だったような記憶ですが……。 (C99はちゃんと調べてないです)

その辺の流れで C/C++ で"真"と値を比較するようなコードは書いたことが無いです。

とまあ、前置きはこれぐらいで require 'php' の実装解説 - 星一の日記

Rubyの基本的なオブジェクトの == メソッドを、PHPの == 演算子の挙動に差し替えるライブラリだそうです。

こんなライブラリの実装が許されるRubyすげー(棒読み)

PHPの == が変態的なのは知っていたつもりでしたが、

PHP の == 演算子の挙動
 null、 false、 true
 
 それぞれ等価なものは以下のとおり。
 
 null
   null、false、0、NaN、空文字、空配列
 false
   null と等価なものに加えて、文字列 "0"
 true
   false と等価じゃないもの (文字列 "0.0"、"0x0"、"00" も true と等価)

"0"がfalseと等価で、 "0.0"や"00"がtrueと等価であるとは知りませんでした。 意味論的に気を利かせるなら、"0"と"0.0"は等価だと思うのですが、これって誰得?

文字列を特別扱いするにしても、awkぐらいに"その値が0か空文字列であれば偽として見なされ、それ以外の値は真であると見なされる。 "ぐらいが扱いやすいと思います。

#awkでも文字列と数字の比較は結構適当にキャストされる。

#0=="0"はtrueなのに、0はfalseで、"0"はtrueとか、遷移律は成り立たない。

mongoDB2009/07/03

あとで試す。

mongoDB via RDB終了のお知らせ-ヽ( ・∀・)ノくまくまー

ドキュメント指向DBの新作らしい。

ようやくCouchDBを試したところなのに……。 時間の流れが速すぎます。

そういえば、CouchDB 0.9は、0.8から要求するErlangのバージョンが上っているので、Ubuntu 8.04では、Erlangを自分でビルドしないといけないみたい?

#面倒臭くなって、CouchDB 0.8に逃げたので、検証はしていない。

','.join() か Array#join か2009/07/01

','.join() がなぜキモイのか

Array#join が

  • 暗示的な型変換を行う
  • Enumerable#join ではなく Array#join

の点においてキモいって指摘については反論の余地は無いと思うけど。

その他の点は言い掛かりの類じゃないのかなあ。 と、つらつら書いていたら、kwatch氏のエントリの方がはるかにまとまっていたので、駄文は大幅に減らした。

でも、気になったのはこの辺

それに対して、Rubyだとメモリ効率はあまり気にせずバンバン一時Arrayを作る。Arrayのメソッドチェーンを作ってキモチイイと悦ぶ。RubyにとってArrayは特別であり、列の汎用型は Array だ。Array以外をjoinしたかったら、 to_a.join すれば良い。

この文化の違いはお互いに理解しにくく、Pythonista から見ると「Arrayしかjoinできないなんてキモイ」し、Rubyistから見ると「Arrayで何が悪い」になってやはり結論はでない。

「Rubyだとメモリ効率はあまり気にせずバンバン一時Arrayを作る。」ってことはないし、 (array.map.map.map なんてメッソッドチェーンがキモチイイとか言う輩は居ないんじゃないかなあ) 「Arrayしかjoinできないなんてキモイ」ってのは普通に感じます。

あと、Pythonistaの人は split が分割される側の文字列のメソッドであることには、むず痒さを感じたりはしないのでしょうか?

でも、別の視点で「連結する側とされる側」というように分類すると、「区切り文字 join 連結される文字」が素直な能動態で、「連結される文字列 (is) join(ed by) 連結される文字」だと無理やりな受動態になるので、''.join() の方が素直だ。

の主張を受け入れるとすると

'sep'.split('string')

の方が素直ってことになるような気がするのですが?

以上、Ruby厨のたわごと。

LLTVチケット2009/07/01

チケット販売について

Tシャツ付きで予約した。

今年はLoppiじゃないのね。 Ruby会議も今年からPayPalになってたし(予約失敗したけど)、何かあったのかな?

あと、販売開始からまる1日は経っているのに、整理番号が2桁なのはちょっと不安です。

天下一プログラマー2009/06/19

天下一プログラマーコンテスト via MEMOはてな支店

名前が素敵。 ってのはともかく、今一ターゲットが不明。 提示されている例題を含めての話。

天下一

天下一なんて冠をつけたからには(うちのSKKのJIS-L辞書には入ってない単語だけど、多分DBを意識しているんだよね?)geek方面を意識しているんだと思う。

で、実際

審査基準
 1. 出題通りに正しく動作するか
 2. 所要時間
 3. コードのエレガントさ

とあるわけだけど、これで例題が

以下の文字列はUTF-8を文字エンコーディング形式とする16進数のバイト列である。
UTF-8でエンコーディングされた文字列として解析した場合、
この文字列の【文字数】を答えなさい。

e4bba5e4b88be381aee69687e5ad97e58897e381af5554462d38e38292e69687e5ad97
e382a8e383b3e382b3e383bce38387e382a3e383b3e382b0e5bda2e5bc8fe381a8e381
99e3828b3136e980b2e695b0e381aee38390e382a4e38388e58897e381a7e38182e3828be38082

ってのは何か違うんじゃないかなあ。

こんな問題に "出題通りに正しく動作するか" 悩んだり、 "所要時間" が計測可能な程時間を掛けたりする "天下一プログラマー" は居ないよ。

"コードのエレガントさ" に関しても、主題に頭を使う部分が全くないので、小手先のそれこそGolf的な凝り方しかすることがないと思う。 んで、(個人的にGolfは好きだけど)これも "天下一プログラマー" の要件では無い。

  • バイト列が実はUTF-8符号化として正しくないとか
  • 幅無しの空白文字が含まれていてこいつの「文字数」は0なのか1なのかとか
  • 解答に与えられる時間が秒単位だとか

ぐらいの制限なりひっかけなりが無いと、コンテストとしての面白みに欠けると思うけど、どうだろう?

蛇足

あと、細かいところだと"16進数のバイト列"って表現もおかしい。 "バイト列の16進数表記"ぐらいなら我慢もできるけど。

"以下の文字列は、ある文字列をUTF-8で符号化したオクテットストリームを16進数表記にしたものである。" が正しいと思う。

ちなみに、僕の解答は

p <<EOT.gsub(/(.)./){$1}.tr("8-b\n",'').size
e4bba5e4b88be381aee69687e5ad97e58897e381af5554462d38e38292e69687e5ad97
e382a8e383b3e382b3e383bce38387e382a3e383b3e382b0e5bda2e5bc8fe381a8e381
99e3828b3136e980b2e695b0e381aee38390e382a4e38388e58897e381a7e38182e3828be38082
EOT

#=> 41

こんな感じ。

MEMOはてな支店 ここの最初の例と全く同じですね。

(追記)

この手の問題をわんこそば形式でひたすら解いていき、一定時間内の正答数を競うコンテストはそれなりに面白いかも。

と思ったけど、それってなんて Project Euler