Debianに入っているrubygemsのパッケージは0.9.4ベースだ。これを
$ gem update --system
してrubygems自体を最新版にアップデートした。現時点での最新版は1.1.1だ。ところが、更新後にgemを使おうとすると
uninitialized constant Gem::GemRunner (NameError)
というエラーが出る。
これは、ローカルでコンパイルした新しいRubyGemsが/usr/bin/gem1.8を生成するが、/usr/bin/gemは依然として0.9.4のままであることが原因。
$ cd /usr/bin # ln -sf gem1.8 gem
してやると、とりあえず治る。
なお、libgems-ruby1.8パッケージは/usr/lib/ruby/1.8以下にライブラリを持っているが、更新されたライブラリは/usr/local/lib/site_ruby/1.8以下に入る。後者のほうが$LOAD_PATHの中で前にあるのでたぶん害はないんだろうけど、気になると言えば気になる。
capistranoでdeployしようとするとき、sshでサーバーにログインしようとする段階で「Net::SSH::HostKeyMismatch, fingerprint my_fingerprint does not match for myserver」みたいなエラーが発生する。
同じエラーに遭遇した人を発見。
net-sshのソースを読むと、known_hostsをサーチしてリモートのfingerprintが入っていたらok, さもなくば例外を発生するというコードになっている。
class HostKeyVerifier
def verify(arguments)
# .... 中略
found || process_cache_miss(host, arguments)
end
end
うん。net-sshとしては、アプリケーションがこの例外をハンドリングして自前でfingerprintの確認UIを出すというのを期待してるんだろうな。capistranoはそれをやってない。
とりあえず、opensshのclientで事前に一度、deploy先サーバーにログインしておく。そうすればknown_hostsに入る。これでエラー無くcapistranoを実行することができた。
私は元来時間に細かいというか、スケジュールが厳密に守られていないと気が済まない。待ち合わせに30秒遅刻したらもう申し訳なくて死にたくなる。目覚まし時計がなった瞬間にぱっちり目を覚まさないと気が済まなくて、そこで1分寝過ごすと(snoozeは付けてるから、実際上は許容範囲なのに)どうしたら良いのか分からなくなる。
この感性と抑鬱状態というのは恐ろしく相性が悪くて、1分寝過ごしてもう首をくくるしかないと思いこんでしまうのは危険きわまりない。それで色々と対応を考えた。
結局、いまの私はあるべき時間をはっきりと意識しないことにした。スケジュールはもう頭に入れるのをやめてgoogle calendarにまかせた。出かけるときも、大体これぐらいの時間に家を出れば間に合うはず、というのをすごくおおざっぱに計算して、はっきりとした時間を知らないでいるようにした。こうすれば、そもそも厳守すべきスケジュールというのが頭の中存在しないので気にしようもない。
アポイントメントがひっきりなしに入っているという身でもないのでこれで済んでいる。どうしても気にしなければならない場合でも、多めにバッファを取って大体の予定は「このあたり、±1時間」と考えているので、その範囲では大抵は厳守できる。ハーフ光画部時間だね。
でも、それでも問題が発生することがある。例えば、ある時間に出社しなければならないとしよう。私は家を出るべき時間を大体の感覚で逆算して、30分のバッファを取って「大体これぐらいに家を出る」とだけ記憶する。 普通はこれでうまくいく。でも、たまたま本来より1時間早く目が覚めたとしよう。そうすると、時間がスケジュール通りでないことに不安になって、そのまま落ち着かないで過ごすことになる。段々体が重くなって、その日は早く目が覚めた分だけなんとかなるとしても、数日引きずったままでいる。翌日は、朝から体がだるい。前日の不安感のせいだ。何もかもがうまくいかなくて、バッファを使い切ってしまって遅刻する。1分遅刻したら、私は不安に苛まれてどうしようもなくなる。そして、もう決して遅刻はすまいとどうしても思ってしまって、おかげで翌日から更に強迫的な時間厳守感覚に追われて物事がはかどらなくなって、結果としてまた遅刻する。以下、悪循環が続く。
なので、最近の、まあ予定時刻に遅れても許される状況というのはありがたいし、お互いのためでもある。「別に遅れてもいいや」と思っている限りは精神的に追い込まれることはないから、従って実際にはまず遅れることはない。私は心根よりも実利を取る主義であるからして、今ではほとんどのスケジュールに関しては「遅れてもいいや」と思っている。おかげで人を待たせることも少なくなった。
それでも、スケジュールをすごくアバウトな感覚でどんぶり勘定しているが故に、偶にダブルブッキングを起こししてそうするとまたどうしようもないのだけれども。でも、これは確率が低い事象なので天災だと思って気にしないことにしている。
頑張って意識を傾ければ「遅れてもいいや」と思えるようになるまで3年掛かった。人間は、特に鬱な人にとってはいい加減であるというのは大変なことだが、でも大切なのである。これからも適当に場当たり的に、深く考えずに生きていていけるように精進したい。
この記事は、先日開催した第3回 RHGの逆襲のまとめみたいなものである。と、同時に『初めてのRuby(仮題)』の宣伝である。
Rubyはクラスベースのオブジェクト指向だから、メソッドの情報はクラスに属している。インスタンスメソッドを呼び出すときには、そのオブジェクトの属するクラスを調べて、そのクラスの持っているインスタンスメソッドの中から探す。
でも、Rubyの場合は例外がある。1つはモジュール。モジュールはクラスではないのに、でもインスタンスメソッドを提供している。1つは特異メソッド。特異メソッドは特定のインスタンスに直接所属するメソッドだ。
でも、ここには実装上のトリックがある。Rubyにとってはモジュールのインスタンスメソッドも特異メソッドも、等しくクラスに属するインスタンスメソッドなんだな。
モジュールをクラスにincludeすると、Rubyは内部的にモジュールの「身代わり」となるクラスを作成する。RHGではこれを「化身クラス」と呼んでいるので、以下ではそれにならう。
化身クラスはメソッド表(名前からメソッド本体を参照するHash)をモジュールと共有している。だから、モジュールが提供するのと同じインスタンスメソッドを提供していると言える。
includeが行われたタイミングで、Rubyはクラスの継承ツリーにこの化身クラスを挟み込む。
class Cattle; end class Yapoo < Cattle include FlowerGlowable end
みたいなケースを考えよう。今、モジュールFlowerGlowableの化身クラスをFlowerGlowable′と書くことにする。
includeするまではYapooの親クラスはCattleだ。includeすると、Cattleの子はFlowerGlowable′、FlowerGlowable′の子がYapooという構造になる。この構造は、Yapoo.ancestorsみたいなのを実行すると見て取ることができる。
特定のオブジェクトだけ、他の同輩たちには無い特別なメソッドを持たせたいと思ったらどうするだろう。特異メソッドとは要するにそういうものだ。
C++だったら、特別なメソッドを持った子クラスを作ってSingletonパターンを適用するというやりかたが選択肢に挙がるだろうなと思う。Rubyの特異クラスとはそれ、そのものだ。
クラスYapombのインスタンスkayoに特異メソッドを定義すると、Yapombを継承した新しいクラス(kayo)を作る。そして、新しいクラスにインスタンスメソッドを定義する。これが特異メソッドの正体である。
それからRubyは、インスタンスkayoが所属するクラスを新しいクラス(kayo)に書き換える。そして、ここでいう新しいクラス、のことを特異クラスと呼ぶ。特異クラスをinspectするとRubyでは#<Class:#<Yapomb:0xXXXXXX @name="kayo">>みたいに表示されるけれども、ここではRHGの表記に倣って(kayo)のように表記する。


特異メソッドを実装するのに特異クラスを使う必要はないし、Matzは当初は他の案も検討していたらしいと聞いた。例えば、直接オブジェクトにメソッド表を持たせても良いわけだ。
つまり、特異クラスという存在はMatz's Ruby Implementationの実装の詳細であり、Rubyの公式な仕様ではない。RHGにはそう書いてある。
でもなー、特異クラスは非公式という前提は特異メソッド定義式を導入した時点で破綻していると思う。既に、私みたいな特異クラス好きの間ではclass << obj; self end として特異クラスを取り出すイディオムは常識なわけで、Railsでも随分使われている。そこで、[ruby-dev:34191]みたいな提案も出てくるわけだ。
ついでに言えばクラスメソッドとは、クラスの、Classオブジェクトとしての特異メソッドである。別の言い方をすればClassクラスを継承した特異クラスのインスタンスメソッドである。
クラスの特異クラス、これはクラスのクラスだからメタクラスと呼んでも差し支えない。Ruby界の英語ではmetaclass, singleton class, eigenclassという述語が混乱しているけれども、私としては次のように提唱したい。
metaclassもまたオブジェクトであり、特にkind_of? Classである。では、metaclassのクラスは? つまり、metametaclassの正体は何者か。
この意味では星さんの記事は誤解を与える恐れがある。
class << obj; end
この式の意味するところは、
だ。
従って、それまで独自の特異クラスを持っていなかったオブジェクトも特異クラスを持ってしまう。つまり、今オブジェクトが真に属しているクラスはこのイディオムでは取得できない。
ちなみに、真に属する、とか言ってるのは、Object#classやClass#superclassのようなメソッドは特異クラスや化身クラスをスキップしてその親クラスを返すせいだ。これらの特殊なクラスはRubyレベルでは原則として目に見えなくて、操作できないのだ。
evil-ruby というgemがある。DLライブラリの力を借りてスーパークラスの書き換え、所属しているクラスの書き換えと言ったRubyが禁止している動作を無理矢理実現してしまう邪悪なgemだ。
これを使えば「真の」所属クラスも取得できるんじゃね? と、RHGの逆襲 第3回で言った。
でも、今調べたらその機能はなかったのでevil-rubyにパッチを書いた。あとで本家に送っとく。次のメソッドを足した。
evil-rubyは1.9対応が完全ではないので、ついでにClassクラスの処だけ直しておいた。
修正版evil-rubyと次のスクリプトを使って階層を辿った。
require './evil'
class Cattle; end
class Yapoo < Cattle; end
[Yapoo, Class, Object].each do |start|
puts "#{start.inspect}:"
puts "\tancestors:"
start.ancestors.each do |klass|
print "\t\t#{klass.inspect}, meta's:"
p klass.classification
end
puts "\tmeta's"
start.classification.each do |klass|
print "\t\t#{klass.inspect}, ancestors"
p klass.actual_ancestors
end
end
オブジェクト-クラス-メタクラス-メタメタクラスの階層を辿るとこうなる。これはRuby 1.8の場合だが、1.9の場合でもBasicObjectが入るだけで基本的に変わらない。
つまり、初期状態ではメタメタクラスというものは定義されていないんだな。メタクラスに対して特異メソッドを定義しようとしたとき、初めてメタメタクラスみたいなものが作成されて、その場合は星さんの記事の通り1.8と1.9で挙動が異なる。
……というようなネタを交えつつRuby入門するための入門書『初めてのRuby(仮題)』を書いた。さすがに、入門書なのでここまで深く突っ込んではないけど、その分だけ解説も上記よりは少し丁寧なはず。
で、本はオライリー・ジャパンより動物本の1冊として6月に刊行される予定である。動物は未定みたいだけど、Rubyコミュニティから希望を出したら反映される余地ってあるのかな? 聞いてみよう。
それにしても、一昨日脱稿してようやく自分がいかに緊張していたか気がついた。初の書籍執筆だもん。正直、今になって「あー、こっちの解説のほうが良かった」とか言う点も出てきている。もう少し肩の力を抜いて書ければ良かったかな。
これらの改善点は可能なら初校段階で入れるし、「(ただでさえスケジュール圧してるので)無理」と言われたらこのサイトでフォローアップしていくつもり。
若年者(年齢の線引きはおいといて)のように価値判断が未発達な人間に見せないほうが良い情報があることは認めよう。それにしても、側にいる大人が日常的な指導や適切なフォローをすればカバーできるとは思うけどね。
でも、何度でも言うけど、現在の技術的な水準では、webコンテンツのうち「有害」なものを検出するには無理がある。もしそれを完璧にできるって言う人間がいるなら、その人に国がちょっとした助成金を出すべきだ。そうすれば、みるみるうちにgoogleやmicrosoftやyahooなんか霞んでしまうはずだから。
つまりは、それぐらい、「有害」なものを検出するというのは技術的に難しい。貴重な情報を誤って「有害」と見なしてしまったり(false positive)、そのくせ露骨な性暴力コンテンツみたいなのを「有害でない」とみなしてしまう(false negative)。これが現代の技術の限界だ。
若干の問題があってもやれることはやるべき? いや、問題が多すぎると言ってるんだ。false positiveとfalse negativeがあまりも多すぎる。そしてこの両者は、一方を減らそうとすれば他方はますます増えていくという関係にある。
また、現状で行われている各インターネット接続会社、携帯電話各社の実施方針にも問題がある。同性愛や性同一性障害に関する問題を有害だと断定していたり、その他諸々。これは「同性愛的なアダルトコンテンツ」の話じゃないよ。
同性愛者団体はインターネットという媒体を通じて、同性愛ということで悩んだりからかわれたりしている子供に対して「生きろ」「こうやって大人に助けを求めればいい」というメッセージを送ってきた。性同一性障害者団体もそうだ。現状のフィルタリング実装は、このようなメッセージが子供に届かないようにしようとしている。
昔はネットが無くてもやっていけた? 嘘をつけ。マジョリティはそうだったかもしれないが、マイノリティはそうじゃない。自己の中心的な属性を否定するような情報ばかりに曝されて人格形成で大きなハンディキャップを負い、無用な自己否定感を植え付けられ、あるいは自死に追い込まれてきたんだ。
そして、そのような子供に適切な手をさしのべられるほど知識のある大人は近くにはいなかった。なぜならば、マイノリティだからだ。それに対して活動している大人もそんなに地理的に近くにはいない。
インターネットの普及によりようやく、こうした子供に手をさしのべられるようになってきた。webフィルタリングは、このような子供を見殺しにしようとしている。
と、いうようなことをたぶん世間は知らない。善意で法案をまとめている議員もおそらく。
だから、これはマスメディアに打って出ないとだめだ。ということで、さしあたって大手新聞各社に投書を送ったけど全滅だなぁ。まあ、私の書き方が悪かったのかもしれんし、みんなも投書してみてはどうだろう。
もともと今年の上半期はRubyに費やすつもりで活動してきた。といっても大部分は本を書いていただけだけど。
今後やりたいと思っていることを挙げる。
RubyはPHPだのPythonだのに比べるとドキュメントが不足してる。PHPは嫌いだけど、あの見るだけでも涎の出てくるマニュアルは素晴らしい。PHPの隆盛もさもありなん。Pythonは、あのstrictさは完全に文化なのでしょう。PerlにしたってCPANモジュールにはPODが必ず付いているし。
それにひきかえRubyは、未だに標準添付ライブラリの完全なリファレンスすら完成していない。メンテナンスも不十分だし。ソースコードに入ってるコメントが間違ってたり、新しいコマンドラインオプションがマニュアルに反映されてなかったりもした(そのままリリースしちゃったんだよ? 信じられる?)。
これは別にRuby開発陣の体質の問題とかそういうのじゃなくて、単純にオープンソースの品質を担保する目玉と手の数が足りてない。だから、私は目玉と手を1組提供する。幸い、コミッタとして「誰も気づいてないだけ」のミスは発見し次第修正できる立場になったし。
本にかまけて「るりま」はさぼりがちだったけど、精進しよう。組み込み/標準添付ライブラリの完全なリファレンスマニュアルを目指して。
古いライブラリには未だに価値あるものも多い。最近のお行儀の良いRubyにはない野性味を学ぶことができるものもある。でも、gem化されていないので新しいRubyユーザーは存在を知らなかったりする。
ライセンスを調べてgem化して、あるいは「るびま」に記事を書いたりして価値あるライブラリを知らしめたい。というか、rdtoolの扱いの軽さが許せない。RD最高。
私ゃ、やっぱりC++出身者で、そして他人に対して押しつけがましい人間なんだな。本を書いていても「文法制約はないけど、でもこうすることになってる」「こういうものだ」っていう記述が結構目立って、私って口うるさい人だなぁと思ったよ。
Rubyの柔軟性は魅力だけど、でもあとほんの少しだけ硬いRubyが欲しい。例えばそれは、Sapphireが言ってるStructured warningだったり、lintだったりする。あとはRailsみたいな種類のメタプログラミングをもう少し高速化できるんではと思ったりもする。
ドキュメントへの指向性といい、なんかひょっとしてPythonistaになっていたら幸せだったのかもしれない。ともあれ、Rubyは現状そういう硬さに欠けているからじゃあなんとかしようじゃないかと。
そう言うわけでRubyをほんの少し硬さを加える提案・実装をいろいろしてみる1人プロジェクト(というか個人的な目標)として"Project Rottenmeier"を宣言する。名前は「アルプスの少女 ハイジ」に出てくる堅苦しくて口うるさい人から取った。「Adelheid, Adelheid!」っていうあの人の声が未だに耳に残ってるよ。そして本を書いてる最中にも、作法的なことを書く度にその声が頭の中に響いた。でも、あの人がいるから家政がぐちゃぐちゃにならずに済んでたんだよね。