5.

ルールを作るものと夢を生きるもの

[o]

 

Through space and time... in his bell jar... on a mission to find himself...

彼は自らの手になる釣鐘型の船に乗り、時空を旅している。自己を見出すために。真実を見出すために。

その男の名は、ドクター・N・ハロルド・チャム

はっきり言って、ドクター・チャムが狂人だという話を聞くのにはうんざりしている。確かに彼は自分で生き埋めになろうとした。確かに彼は姪を感電死させた。確かに、 そう、彼は養老院を爆破した。しかしそれにはすべてしかるべき理由があったのだ。私は彼が正しい選択をしたのだと信じている。

あなたは世間の人と同じ考えだろうと思うが、もし彼にRubyのクラス定義のすべてについて教わる機会があったなら、彼に対してちょっと尊敬の念を抱くようになるだろう。ミックスインについて学んだならなおのことだ。そしておそらくこの章 が終わる頃には、私たちは皆、ドクターの痛ましい過去にとらわれずに彼を見ることができるようになり、もう狂人と呼ぶのはやめるだろう。

もしそれでも彼を狂人と呼ぶ必要があるというなら、私なら線路まで下りて行ってどこかの長い蛍光灯を砕く。すぐ憂さを晴らすといい。私たちが取りかかる前に。

1. これは権利を奪われた人のため

Some people still can't get past what he did.

「私の祖母がいた療養施設は1940年代に ドクター・チャムに吹き飛ばされたんだ。なんて惨劇だろう」

「みんなあいつをグラニーボマーと呼んでたよ。まったく恐ろしい男だ。あいつが私たちを爆破しやしないかと思うと、今でも死ぬほど恐ろしい」

「だけど今度はこっちだって準備してるよ。うちの療養施設にはちょっとした防衛予算があるんだ。毎日午後4時の塹壕掘りだって手伝ってる! それに私たちにゃハーコート将軍っ人がついてるんだ!

ドクター・チャムの人生の中の年を1つあげてもらえたら、その時期における彼の概要を教えてあげるよ。私はそれをRubyのメソッドを使ってやる。これは独立した一片の孤立したコードの塊で、ロボット火山の声にだってつなぐことができる。そんななものが権威ある声優に最高の仕事になるときには。


OK、ここではdefcasewhenに注意してもらう必要がある。範囲は3章で見ているよね。1895..1913という閉じたアコーディオンだ。これは両方の端とその間の値を含んでいる。それから行の終わりのバックスラッシュは行末のEnterキーを無視し、この行にはまだ続きがあるのだととRubyに請け合っている。

ではdefcasewhenに気をつけて。

 def dr_chams_timeline( year )
   case year
   when 1894
     "生まれる。"
   when 1895..1913
     "ミシシッピ州ウィンストン郡のルースビルで子供時代を過ごす。" 
   when 1914..1919
     "ペカンの園芸店で働く。クエーカー教徒を殴る。" 
   when 1920..1928
     "ミシシッピ川を旅しながら考え深い自己改革に従事するウィズダミン川協会に入る。その\
      ウニバーシティにおいて140単位を修了する。" 
   when 1929
     "時間旅行するキジ狩人の小説を書くため、ルースビルに戻る。" 
   when 1930..1933
     "ペカン園芸の保険の仕事で相当なキャリアを積む。経済的に安定し、ブラジルとニューメ\
      キシコで過ごし、珍しい薄い殻のペカンの木を買い占める。彼の名声は高まるばかりだっ\
      た。それから、なんと彼は自分を生き埋めにする。" 
   when 1934
     "小説執筆に戻る。狩人を保険業界の大物に、キジをクエーカー教徒に変える。" 
   when 1935..1940
     "ウィズダミン川協会会長のアーサー・コーンを客として家に招く。5年間一緒に工学と投資\
      を行う。" 
   when 1941
     "ことが面白くなるのはここからだ。" 
   end
 end

まずdef キーワード。これは私たちがする最初のメソッド定義だ。def はただのカーネルメソッドで、Rubyのどこでも使うことができる。さて、これはどうやって実行すればいいのか?

 puts dr_chams_timeline( 1941 )

これは"ことが面白くなるのはここからだ。"という答えを返す。毎回同じ話だ。退屈なら自分の答えを使うといい。上ではcase の答えが必ず文字列になるようにしている。そしてcase 文はメソッドの最後の(そして唯一の)文になっているので、メソッドはその文字列を返すことになる。流れる水は、岩棚から岩棚へとこぼれ落ちる。

case 文について説明しよう。実際私はこれをcase..when文と呼ぶべきだろう。casewhenを別々に使うことはできないからだ。caseキーワードには値がくっついていて、それがwhenキーワードのそれぞれにくっついている値と比較される。最初にマッチした値がcaseに使われ、残りは無視される。同じことをたくさんのif..elsifを使ってやることもできるが、そうすると長くなる。

 case year
 when 1894
   "生まれる。"
 when 1895..1913
   "ミシシッピ州ウィンストン郡のルースビルで子供時代を過ごす。" 
 else
   "この年については記録がない。" 
 end

これは次のように書いても同じだ。

 if 1894 === year
   "生まれる。"
 elsif 1895..1913 === year
   "ミシシッピ州ウィンストン郡のルースビルで子供時代を過ごす。" 
 else
   "この年については記録がない。" 
 end

三重の等号は長く伸びたベルベットのロープで、二重の等号と同様に値をチェックしている。ただ三重の等号の方がロープが長く、真ん中の辺でたるんでいる。あまりきっちりとはしておらず、少しばかり柔軟性がある。

上の例の範囲を見てみよう。(1895..1913)というのは1905と全然等しくはない。範囲(1895..1913)が本当に等しくなる相手は範囲(1895..1913)だけだ。三重の等号は、範囲に対しては隙間を作って整数1905 を入れてくれる。この整数は範囲と等しくはないが、範囲が表す整数の集合に含まれている。場合によってはそれで十分なこともあり、たとえば上で作った年表がそうだ。

これは実際年表のように見えるよね? もちろんdr_chams_timelineメソッドはコードなわけだけど、年表みたいに読むことができ、すっきりしていて愛らしい。

What research revealed.

ドクター・チャムに虐殺された高齢者の中に私の祖母のスーザン・レイ・マッグウィンもいました。私はそれ以来入念な調査をし、私の祖母が死に値する憎むべき女性であったことを知るにいたりました。

私のノートには、祖母の姿を変えるものへの悪魔崇拝、潜水艦のハイジャック、骸骨の誘惑、子どもたちの上に基礎を作って家を建てること・・・まったく病的なことが次から次へと並んでいます。

私はドクター・チャムが彼らを殺してくれたことに本当に感謝しています。あのホームでは巨大なロボットアライグマを建造していたのです。アライグマは人に噛みつくんです!

しかし彼は病気だったのか??

彼はタイミングが悪かったのだ。小説家としては散々だったが、錬金術への挑戦は見込みがあるように見えた。彼はヤギの乳と海塩から脚の痛みを取る万能薬 を作った。ある男はなくした指が1インチ伸びてきたほどだった。足のような臭いがするが暗闇でも目が見えるようになる有機健康煙を作った。水梯子と呼ばれるものにも取り組んでいたが、私は現物を見たことがないし、それについて書かれたものも読んだことがない。登るためのものではありえないだろう。わからないけど。

地元の新聞社が実際ドクター・チャムの元を訪れたことがある。彼らの書評家が彼に4つ星の評価をしたのだ。本当に。その書評家は彼についての記事を書き、そして彼を評価したのだ。

ドクター・N・ハロルド・チャムが姪のことですごく辛く感じていたことは知っておいてほしい。彼はそのショック療法は効果があると思ったのだ。どのみち彼女はポリオのために死んでいたはずだ。彼はチャンスに賭けたのだ。

1941年9月9日、彼は自分の私有する手術室で、ハンナをフェナセチンで鎮静させた後、鼻と舌とつま先と肘に伝導クリップをつけた。弟子であるマービン・ホリオークという名のそばかすの大学生に手伝わせ、彼 が最高傑作(opus magnum)と呼ぶ物質の粉をハンナに振りまいた。粉末のホワイトゴールドが流れを運び、彼女にエネルギーを与え、血を活性化 させ、戦い、打ち破れるようにするのだ。

しかしそれがどんなに失敗したことか。スイッチが入れられたとき、彼女はエビ反りになって足をばたつかせ——カブラム!——それからブロイ オイ オイ クポイ!と叫んだ。彼女の巻き毛に光の壁、そして死の鐘が鳴った。実験は立ち上がるものすごい煙とともに失敗し、彼女の無邪気さは部屋の床と彼らの胸に大きな穴をあけた(何週間も、みんな「あの子にはチャンスがなかったんだ・・・」と口にしていた)。

ハンナのために、私はコードを書こう。

 opus_magnum = true  # 最高傑作 = true
 def save_hannah     # ハンナを救う
   success = opus_magnum
 end

メソッドは自分の島を持っている。そしてメソッドの中で起こることは、まわりにあるただの変数には影響を受けない。ドクター・チャムは姪の病気を打ち破ることができなかった。それはopus_magnum変数がメソッドの鋼鉄の外壁に入り込むことができないようなものだった。

save_hannahメソッドを実行すると、Rubyはopus_magnumが見あたらないと文句を言うだろう。

私はスコープについて話している。顕微鏡(マイクロスコープ)は視野を狭めて拡大する。望遠鏡(テレスコープ)は視野の範囲を押し広げる。Rubyではスコープはメソッドやブロックの中の視野を表している。

メソッドのdef ステートメントは視野を開く。そこで導入される変数名はメソッドの中では見ることができ、意味を持ち続けるが、endで目が閉じられる。メソッドに引数でデータを渡 したり、メソッドからデータを返すことはできるが、メソッドの中で使われている名前はそのスコープ内でしか効果を持たない。

ある種の変数はより広いスコープを持っている。お金の記号で始まる$LOAD_PATHのようなグローバル変数は、どのスコープでも使うことができる。アットマークで始まる@namesのようなインスタンス変数は、クラススコープの中でならどこでも使える。同じことは@@ticketsのようなクラス変数についても言える。クラス変数とインスタンス変数についてはもう少しあとで説明する。

ブロックもスコープを持つが、すこし曖昧で、もっと柔軟性がある。

 verb = '救った'
 ['鎮静剤を与えた', '振りかけた', '感電死させた'].
 each do |verb|
   puts "ドクター・チャムは姪のハンナに" + verb  
 end
 puts "そう、ドクター・チャムは姪のハンナを" + verb 

ブロックはドクターのそれぞれの行動をイテレート(循環)する。verb変数はそれぞれの回ごとに値が変わる。ある回では鎮静剤を与えている。その次では粉を振りかけている。それから感電死させる。

疑問は、ブロックが終わったらどうなるのかということだ。ドクターはハンナを救えたのだろうか?

 ドクター・チャムは姪のハンナに鎮静剤を与えた
 ドクター・チャムは姪のハンナに振りかけた
 ドクター・チャムは姪のハンナに感電死させた
 そう、ドクター・チャムは姪のハンナを感電死させた

ブロックは周辺にある変数を見ることができる。ブロックはverb変数が存在することに気付き、その内容を書き換えたのだ。ブロックが終了すると、ブロックの短い命は終わるが、verb変数は別な生き物として現れる。

ブロックが前に使われていない変数を使う場合には、変数はブロックの終わりとともに消滅する。ブロックのスコープは閉じられ、変数はそれとともに消えてしまう。verbがブロックの前では使われてなかったとしよう。

 ['鎮静剤を与えた', '振りかけた', '感電死させた'].
 each do |verb|
   puts "ドクター・チャムは姪のハンナに" + verb 
 end
 puts "そう、ドクター・チャムは姪のハンナを" + verb 

これはundefined local variable or method `verb' ('verb'は未定義のローカル変数ないしはメソッドです)というエラーになる。

まだ糊のきいた刺繍のあるドレスを着ているが、口の隅が暗い紫色になった少女の死体を運び出すというのは、優れた科学者にとっても難しいことだったのに違いない。ドクター・チャムの日記には、 輝く金と焦げたレースを身にまとったハンナの幽霊に苛まれたことが書かれている。妄想は次第に大きくなり、彼は地獄の犬と、復讐に燃える天使の大きな手に追いかけられた。

何週間もたたぬうちに、彼は去った。この悔恨から逃れ、この惑星から彼を飛び立たせる爆発とともに消えた。

そしてあなたが今これを読んでいるにしても、この瞬間にどこかで、孤独なドクター・チャムは釣鐘型の乗り物に乗り、60年の旅の後に遠く離れた惑星に降り立っている。新しい世界が視野に入り、近づくにつれ惑星の地平が広がり、 釣鐘が怒る天を駆け抜け、オーロラと太陽風を引き裂くのとともに、ドクター・チャムの目は揺り覚まされる。

Safe landing.  Amazement.

 

 

美しい

あなたが目撃しているのは、ドクター・チャムの惑星エンダートロムへの着陸だ。私にわかる限りで言うと、彼はこの惑星でほとんど何も起こらない荒涼とした季節に降り立った。ほとんどの住人は心をぼんやりしたざわめきの中に閉じこめ、一部の知恵と三部の靄からなる退屈な幽霊へと分解し ていた。

エンダートロムの歴史と天候についての私の知識は、私の娘のオルガン教師との付き合いから得たものだ。彼はこの惑星で育ったのだ。

Dead husbands could destroy the Doctor.

「お年寄りの人たちの中にはドクター・チャムがまだ宇宙を飛び回っていると思っている人もいます。なんてたわごとかしら!」

「もし悪いグラニーボマーが宇宙にいるのなら、私の夫のチャールズ——1997年に亡くなりました——彼の魂の安らかならんことを——彼が今では宇宙にいて、レーザーをぶちかまし、彗星の尻尾に乗っている わ」

「ドクターがチャーリーに勝てる見込みはないわね。チャーリーが彼にとどめを刺すでしょう・・・ドクターがチャーリーの欲しがるテクノロジーを持っていれば別だけど。その場合はチャーリーはドクターと同盟を組んで、爆破事件がもっと起きることになるわね」

私の娘のオルガン教師は、ちゃんと約束を守るように繰り返し言ってやる必要があった。彼は変な時間に訪問することがあり、緊急の電話にも即座に出た。彼が最後に明かしたのは、彼がエイリアンで、起きている時間が540時間続くということだった。私は彼にすごく元気づけられ、2060年まで続くことになる契約関係を彼と結んだ。

ドクター・チャムは(彼の懐中時計で)3日間暗い空気の柱の中を旅し、不毛な惑星のほこりっぽい風を吸った。しかし3日目に、荒涼とした季節が終わり、野生のリンゴの花と、霞んだ城に飾られた見事な光景が拡がるのを、彼は目の当たりにした。

2. コンピュータのある城

The panoramic vales of Sedna on Endertromb.

「これこそ城の未来だ!」

恐れを知らない我らがドクターは異星の城へと向かい、花の間を走り抜けた。地面は彼の踵の下を流れ過ぎた。城が地平線から徐々に姿を現してきた。彼は馬があればと思ったが、馬は現れなかった。そ れで彼はその惑星が心を読んで望みをかなえてはくれないのだと悟った。

私の娘のオルガン教師の説明によれば、その惑星は心を読むことができ望みをかなえることができるということだった。ただし同時にではなかったのだ。

ある日私がそのオルガンの名人を質問攻めにしていると、彼はチーズ色をしたレポートパッドに次のようなRubyのコードを書いた。(そして奇妙なチーズの臭いがどこからともなく漂ってきたが、それがどこなのかわからなかった。)

 require 'endertromb'
 class WishMaker
   def initialize
     @energy = rand( 6 )
   end
   def grant( wish )   # 望みをかなえる
     if wish.length > 10 or wish.include? ' '
       raise ArgumentError, "間違った望みです。" 
     end
     if @energy.zero?
       raise Exception, "エネルギーが残っていません。" 
     end
     @energy -= 1
     Endertromb::make( wish )
   end
 end

これはウィッシュメーカーだ。

正確にはそうでなく、ウィッシュメーカーの定義だ。これはRubyのクラス定義になっている。このコードはあるオブジェクトがどのように振る舞うかを記述 している。

毎朝、ウィッシュメーカーは最大5つのかなえられる望みで活動をはじめる。太陽が昇るときに新しいWishMaker が作られるのだ。

 todays_wishes = WishMaker.new

new メソッドはクラスメソッドで、新しいまっさらなオブジェクトを作る。それはまたオブジェクトのinitialize メソッドを自動的に呼び出す。WishMaker の定義では、initalize メソッドは@energy = rand( 6 )という一行のコードになっている。

rand( 6 )は0から5の数字を選ぶ。この数はその日の分の望みの数を表している。だからときどきウィッシュメーカーが1つも望みをかなえてくれない日もある。

乱数は@energyという名前のインスタンス変数に代入される。このインスタンス変数はクラスの中であればいつでも使うことができる。ただしクラスのスコープの外では使うことができない。

3章でインスタンス変数について簡単に見て、それを属性(アトリビュート)として考えることにした。(アットマークアトリビュートを意味するのだ。) インスタンス変数はどんな種類の情報でも格納することができるが、多くの場合、そのクラスで表されるオブジェクトの情報を格納するのに使われる。

上の例では、その日その日のウィッシュメーカーは、自身のエネルギーレベルを保持している。ウィッシュメーカーがマシンだったら、中に残っているエネルギーを示す計器がついているのを目にしているところだろう。インスタンス変数@energyはその計器 の役割を果たす。

 todays_wishes = WishMaker.new
 todays_wishes.grant( "枝角" )

OK、一歩下がって、この例が理解できたか確かめてほしい。WishMaker クラスは、魔法の望みプログラム全体がどう動くか記述した概略だ。壺に入った実際のジニーではなく、舞台裏の事務処理を表している。これはジニーが指針とするルールと義務だ。

todays_wishesが壺の中のジニーだ。私たちはそれにかなえてほしい望みを渡す。枝角がほしいんだ、ジニー。(あなたがこの例から本当に枝角を手に入れた としても、私はその話を聞きたくない。草原で新しい仲間たちと跳ね回るといい。)

前の章で覚えたのは、Rubyには2つの部分があるということだった。

  1. ものを定義する。
  2. それに行動させる。

Rubyにおける行動とは何か?  メソッドだ。そしてあなたは今、Rubyに組込まれた定義言語を味見したというわけだ。defを使ったメソッド定義に、classを使ったクラス定義だ。

あなたの教育のこの時点までくれば、Rubyではすべてがオブジェクトだということは理解しやすくなっていると思う。

 number = 5
 print number.next                  # numberの次。'6'がプリントされる

 phrase = 'wishing for antlers'     
 print phrase.length                # phraseの長さ。'19'とプリントされる

 todays_wishes = WishMaker.new
 todays_wishes.grant( "枝角" )

そしてそれぞれのオブジェクトの裏にはクラスがある。

 print 5.class                       # 'Fixnum'と表示
 print '枝角がほしい'.class            # 'String'と表示
 print WishMaker.new.class           # 'WishMaker'と表示

ドクター・チャムが地形を横断して急いでいたときにウィッシュメーカーを目にすることはなかった。ウィッシュメーカーは彼が着陸したセドナの谷からずっと離れた場所にあったのだ。幾重もの藪に覆われた絶壁を下り、 そこから(小さな1” x 6”の紙切れに書いた)望みを投げ込むと、それは口を開けた間隙に消えていく。望むらくは、それがトカゲの背中に着地して捻れた小さな角に張り付いてくれんことを。

あなたの望みがそこまで無事にたどり着けたとしよう。そのあと痩せたサラマンダーはよじれた木々の間を下って行き、朽ちた教会を急いで走り抜ける。その教会は岩だなを越えて険しい谷へと押し落とされる。中にいた任期の切れた牧師はかろうじてその落下を切り抜け、その小さな両生類を殺し——祝福された金の鎖を使って絞め殺し——そして年に一度の「 汝自身を知る」朝食のためにそれを取っておく。彼はあなたの大切な小さな望みを踏んづけて、盗人たちが押し入ったとき、その紙切れは依然そこに、彼の踵に張り付いている。盗人たちの好きな拷問方法はもちろん、牧師を頭からつま先まで薄いスライスにするというものだ。 そうすれば誰が証拠を見つけられる? そして彼らは最後の靴底の薄いスライスを刻み、幸運のお守りにゴムの戦利品を取っておく。この盗人たちはすごく熱心にカヌーを漕ぐ。彼らは流れの中をパドルで素早く叩き、大きな船外モーターのしぶきが上がる。靴底は男の1人のベルトに軽く留められている。そしてぞっとする老いたコイが飛び上がり、その履き物のわずかな断片をかっさらう。盗人たちは水の中を覗くことはできるが覗こうとはしない。もし覗いていたなら、彼らは何百万もの針のような光ファイバーの詰まった強力なケーブルを見たことだろう。実際、その魚は惑星エンダートロムの中心的な機構に直接接続された周辺機器なのだ。この魚 に飲み込ませることさえできれば、あなたの望みは無料で本拠へと送り届けられるのだ!

そしてこれが、この惑星の子どもたちの望みがかなえられる方法なのだ。

私の娘のオルガン教師はウィッシュメーカーのクラスを書き上げると、次に惑星のマインドリーダーのクラスを書いた。

 require 'endertromb'
 class MindReader
   def initialize
     @minds = Endertromb::scan_for_sentience # 意識をスキャンする
   end
   def read
     @minds.collect do |mind|
        mind.read
     end
   end
 end

これまでに見てきたものと同じように、MindReader オブジェクトが新しく作られるときにはinitialize が実行される。initalize は惑星のマインドシェアをスキャンする。それらのマインドは配列に格納されているらしい。それというのも、後の方でcollect メソッドを使ってイテレートされているからだ。

ウィッシュメーカーとマインドリーダーはどちらもEndertrombという名前のクラスを参照している。このクラスはendertromb.rbというファイルに格納されていて、コードrequire 'endertromb'によりロードされる。あなたも仕事の一部を他のクラスを使 ってやるようになるだろう。この本の後半の大部分は、Rubyにロードできる様々な有用なクラスの探求にあてられる。

 

ドクター・チャムは思い切って中に入る

ドクター・チャムが城に近づくと、惑星は彼の考えに気づき、彼の驚きと期待を感じ取ったが、ドクター・チャムが感じたのは死のような静寂だけだった。彼は開いたゲートの階段を上り、 とても美しい建築の入り口に来た。およそ誰もいそうになかった。

彼がノックしてしばらくして、それは報われた。

Blocky whale greeting.

コンコン

「私はドクター・チャム。宇宙旅行者だ。中に入ってあなた達のことを調べてもかまわないか?」
「いいよ」

「じゃあね」
「すごい!」

彼はその赤ちゃんクジラが断固とした風船のように上っていくのを見ていた。彼は最初の異星人との出会いに驚き、それがあまりに早く過ぎてしまったことを少し気にかけていた。まあ、中で待つことにしよう。

城の入り口を通り抜けながら、出迎えたのがどん欲なかぎ爪を持った巨大な鷲でなかったのをありがたく思った。あるいは巨大なネズミの頭とか。あるいは人間サイズのハリケーンとか。ただのずんぐりした小さなクジラだ。

「この城には腰掛けられるところがないな」と彼は言った。

はじめ彼はとても暗い玄関ホールに入ったものと思っていたが、目が慣れてくると、入り口はトンネルに繋がっていたことがわかった。城の扉は長くて平らな岩の板でできた通路にそのまま繋がっていたのだ。ある部分はよく整っていて回廊を思わせた。別な部分は狭くて傾いており、先の方は視界から見えなくなっていた。

通路はドアのない小さな冷蔵庫で照らされていた。それは一抱えのキャベツを入れられるくらいの大きさがあり、足下にあった。中を覗いてみると空っぽで、内壁はすべての面が照らされいて、整然と氷の破片が作られていた。

氷のかけらに触ると、指先にくっついた。ドクターは手をその氷にこすりつけた。皺にはどろが残っていたが、入浴に対する欲求のごく一部は満たすことができた。何年になるのだろう? 10年? 30年?

ある区画では、通路に沿って長い布のチューブが散らかっていた。それから磁器のシャベルとバケツに入った明るいピクセル物質があった。

彼はトンネルから掘り進めて作られた部屋に出た。地面に空の亀の甲羅がいくつかあり、大きな照らされた壁があった。彼は驚いて部屋の中を眺めていた。ここは何だろう?  すこし甲羅の上に腰掛けようかとも思った。入り口にある待合室にようやくたどり着いたのかもしれない。しかし一方で、座ったとたんに甲羅の穴からクモがあふれ出てくるかもしれないと思った。それで彼は先に進むことにした。

 

城のポケットの中での食事

通路を進んでいくと(中央トンネルが分岐してそれからもっと大きな何もない洞窟に合流した)、彼は所々でテーマがあるのに気付いた。いくつかの部屋はポンプ装置で占められていた。別なところでは、布とにかわの桶で占められていた。彼はビロード張りの空洞 から聞こえてくる声の方に進み、行き止まりまで行った。壁の目の高さのところに小さな部屋が彫られていた。

壁に近づいてみると、その小さな穴の中で、2匹のツチブタがテーブルについて食事をしていた。

彼らはドクターを穏やかに見つめていた。どちらも自分の2倍の大きさのある、割って背を下にテーブルに載せられた甲虫をむしゃむしゃと食べていた。

「こんにちは、小さな人形たち」とドクターは言った。彼らは噛み終え、すましてフォークを手にしたまま、ドクターを見つづけていた。

「私の姪のハンナが君たちに会いにここへ来たのじゃないかと思って」ドクターは油断のないミニチュアツチブタに話しかけた。「あの子は君たちを複雑な人形劇だと思うだろうね」。彼はそのダイニングや、何セットもの皿が入った棚やハンドタオルに目を向けた。小さなウサギがマシンの上から半分突き出していて、クリーム状の赤い麺が下から こぼれ出ていた。部屋の奥のドアは半開きになっていた。そのドアを通して、椅子と唸りを上げるモーターのある部屋を垣間見ることができた。

「子供はみんな人形の家を欲しがるよね」と彼は言った。「ハンナは、さっき言ったように私の姪だが、スピンドルの前に座って毛糸を紡ぐからくり人形を持っている。もちろん本当にではない。人形は全然毛糸を作ったりはしない」

ツチブタの一匹が床の上げ蓋を開いて中のボタンを押すと、灯りがついた。それから小さなフィルムプロジェクタがゆっくりと支柱に載って上がってきた。もう一方のツチブタは座っ たままドクター・チャムを見ていた。

「それでもハンナは 人形の家に行って想像上の毛糸を束ねて集めてくる。それを母親、つまり私の妹に渡す。妹はハンナに調子を合わせるのがうまくて、それで人形サイズの服を縫ってやる。その服をハンナは人形の家に持って帰る。

そして人形に『ほら、見て、あなたの努力と根気が、このきれいなドレスになったのよ。これで知事さんのお屋敷で今夜あるパーティへの警察署長さんのお誘いを受けられるわね』と言 うんだ。ハンナは署長役の警察官の制服を着た人形も持っているのだが、それは署長にしてはやせこけているので、ちょっと整形してやる必要があるだろうね」

プロジェクタ担当のツチブタはリールをセットして向こうの壁に狙いをつけた。フィルムが回りはじめ、ツチブタは席に着いた。壁の上に緑色の四角形が現れた。用心深いツチブタは相変わらずドクター・チャムを見ていた。

「君たちのフィルムはカラーなんだね」とドクター・チャムは言った。「なんて可愛らしい小さな生き物なんだ」

映像はつづいて青い四角形を映し出した。それから赤い円。それからオレンジの四角。用心深いツチブタも向こうを向き直って映像がピンク色の三角に変わるのを見た。それからツチブタたちは食事を再開した。

紫の星。赤い四角。静かな状況の中で、ドクター・チャムはプロジェクターのうなる音を聞くことができた。 線路にそってギアを回そうとする歩みの遅いオルゴールのようだった。

「食事を楽しむといい」とドクター・チャムは言って、礼儀正しく踵を返し、元来た方へ歩いていった。

 

ものごとが始まるもうひとつの袋小路

ドクターは城のトンネルの中で道に迷ってしまった。何も見覚えのあるものがない。しかし彼はあまり気にかけてはいなかった。別な惑星にいるのだから、もとより迷子のようなものだ。

彼は曲がりくねったトンネルを進みながら道を思い出そうとしたが、道を気にするには探索するのがあまりに面白かった。彼は1つのトンネルを深く降りて行った。坂があまりに急なので、出っ張りと出っ張りの間を飛び 移りながら、注意深く足がかりを探す必要があった。その場所の重力は地球とは違っているようで、彼は楽々と歩みを進めることができた。

しかし彼には自分がどこにいるのか知るすべがなかった。城の領域はすでに出ているのではないかと思った。これほど深く、これほど長く歩いたのだ。ドアを入ってから1時間はたつ。トンネルはまた上りになったので、どこかの新しい家の中に出るかもしれない。あるいはマンホールに出て、そこから城が見えるかもしれない。たぶんこの道をそんなに遠くまで進むべきではなかったのだろう。その辺で何かが冬眠したりしてないことを願った。

トンネルは先がなくなった。暗い行き止まりだ。

At the end of the tunnels: a computer and a book.

地下埋葬所の奥・・・

・・・マシン・・・

・・・マシンの横には、1冊の本。

ホワイの(感動的)Rubyガイド

彼には時間があったので、その本を読むことにした。彼はキツネたちとピックアップトラックを盗んだヤマアラシの追跡の話を読んだ。彼はエルフとハムの話を読んだ。彼は自分自身の絵を見、自分の奮闘が描かれているのを見た。彼はRubyを学びさえした。それがどういう終わりを迎えるのかを見た。

私が彼だったなら耐えられないだろう。しかし彼は耐えた。そして腹を据えて、何が起こるのかを見ることにしたのだ。

コンピュータモニタに、ドクター・チャムは点滅するirb のプロンプトを見た。あなたもドクター・チャムのように、「トラのチョッキ」(この本の最初の拡張パックで、インタラクティブRubyの基本について書かれている)を読んでirb のプロンプトがわかるようになっているかもしれない。

さっきまで彼は歩いてトンネルを探索してきたが、今度はプロンプトでマシンの設定を探索している。彼は本を元の場所に戻しておいた。もう必要がない。彼がその本を使おうが使うまいが、それはすべて起きることなのだ。

彼は次のように調べはじめた。

 irb> Object::constants
   => ["Marshal", "String", "Dir", "LoadError", "Float", ... そのほか ]

このコマンドはすべてのトップレベルの定数をリストアップする。クラス名もまた定数としてリストアップされる。だからこのリストはRubyにロードされているものを調べるためのいい方法なのだ。

彼はリストの中に見慣れないものがないか探した。Rubyにもともと入ってはいないものだ。MarshalStringDirLoadErrorFloat。これらはどれもRubyにはじめからあるものだ。

しかしリストの先の方を見てみると——

 ... "Struct", "Values", "Time", "Elevator", "Range" ...

Elevatorだって?  これは間違いなく調べるべきクラスだ。彼は調査を進めた。

 irb> Elevator::methods
   => ["method", "freeze", "allocate", ... 長いリストがつづく ... ]
 irb> Elevator::class_variables
   => ['@@diagnostic_report', '@@power_circuit_active', '@@maintenance_password']
        (診断レポート)                (電源回路アクティブ)           (保守用パスワード)
 irb> Elevator::constants
   => []

Elevatorクラスにはたくさんのメソッドがあるようだ。その多くはRubyのオブジェクトがみんな持っているもののようだった。たと えばmethodfreezeallocateはRubyのどのクラスにもある。(Elevator::freezeElevatorクラスが変更されないようにする。Elevator::allocateinitializeメソッドを呼ばずに新しいElevatorオブジェクトを作成する。)

class_variables はドクター・チャムには興味深いものだった。このエレベータは本物のようだ。一方constantはなく、これはElevator クラスの中にネストされたクラスがないことを示している。

彼はElevator オブジェクトを作ろうとした。

 irb> e = Elevator::new
 ArgumentError: wrong number of arguments (0 for 1), requires a password
         from (irb):2:in `initialize'
         from (irb):2:in `new'
         from (irb):2
         from :0

パスワードがいるようだ。適当に試してみた。

 irb> e = Elevator::new( "going up" ) # 上ヘ上がる
 AccessDeniedError: bad password
 irb> e = Elevator::new( "going_up" )
 AccessDeniedError: bad password
 irb> e = Elevator::new( "stairs_are_bad" ) # 階段は嫌いだ
 AccessDeniedError: bad password
 irb> e = Elevator::new( "StairsAreBad" )
 AccessDeniedError: bad password

こんなことをやっていてもしょうがない。いや、待って! メンテナンスパスワードだ。確かclass_variablesの中にリストされていた。

 irb> Elevator::maintenance_password
 NoMethodError: undefined method `maintenance_password' for Elevator:Class
         from (irb):1
         from :0

うーん。インスタンス変数はオブジェクトの中でしか使えないのだ。そしてクラス変数もクラスの中でしか使えない。どうやってパスワードを取り出せばいいのだろう?

 irb> class Elevator
 irb>   def Elevator.maintenance_password
 irb>     @@maintenance_password
 irb>   end
 irb> end
   => nil
 irb> Elevator::maintenance_password
   => "stairs_are_history!"
        (階段は過去のものだ!)

やった! パスワードを手に入れた。どうやったのかわかった?

彼はElevator クラスにクラスメソッドを追加したのだ。Elevator の新しいクラス定義を書くと、Rubyは既存のクラス定義を変更してくれる。これってすごいと思わない?

クラスメソッドは通常二重のコロンを使って呼ばれる。しかしピリオドも問題なく使える。Elevator 自体はクラスだが、RubyはあなたがElevator.maintenance_passwordを呼ぶとき、クラスメソッドを呼んでいるのだとちゃんとわかる。二重のコロンを使うのは、コードを読む人にそれがクラスメソッドだとはっきりわかるようにするためだ。

それだけのことだ。クラスメソッドというのは少し変わっている。普通はクラスに直接情報を持っておこうとは思わない。しかしそのクラスのすべてのオブジェクトの間で共有すべき情報がある場合、クラスをその保存場所として使うのは理にかなっている。@@maintenance_password が個々のオブジェクトでなくクラスに保存されていたのは理解できることだ。そうすることで、オブジェクトはクラスに手を伸ばして共有パスワードを見ることができる。

パスワード保護の仕組みは、おそらく以下のようになっているのだろう。

 class Elevator
   def initialize( pass )
     raise AccessDeniedError, "bad password" \
       unless pass.equals? @@maintenance_password
   end
 end

このようにクラスをパスワード保護するのは意味がない。Rubyの中のものはすべて、入れ替え、上書きし、作り直せるからだ。ドクター・チャムはパスワードを手に入れ、エレベータの所有権を得た。

 irb> e = Elevator.new( "stairs_are_history!" )
 #<Elevator:0x81f12f4 @level=4>
 irb> e.level = 1

コンピュータ端末の裏にあるエレベータの扉が開いたとき、ドクター・チャムはその真ん前に立っていた。圧倒的な達成感と、この先に待ち構えていることに対する興奮に包まれて、彼はエレベータに乗り込み、4のボタンを押した。

3. 娘のオルガン教師の話のつづき

私に娘がいると聞いたら驚くと思う。私が書くものには、麻痺や幼児的な精神の兆しが見られると思うだろう。安心していい。私には娘はいない。しかしそんなことで 娘の音楽教育の手はずを整えるのを私が思い留まったりはしない。

前に言ったように、惑星エンダートロムのこの精巧な歴史は、私が廊下をさまよい、しっかりボタンが埋め込まれたソファを指先でなぞり、私の娘のオルガン教師が演奏するパイプの響きに満たされているときに見 い出したものだ。彼の奏でる音は彼の家の壁に深く空ろに反響し、私はいつしかそれを不吉な沈黙と取り違えるようになった。そして自分の思考の深みに入り込むのがより容易になっていることに気付いた。 太古の惑星と、その わかりにくい哲学について考える。殉教者の皮膚をなめして作った肉体の神殿。敵を飲み込んで何十年も閉じこめ、肋骨の階段を引きずり上げ、引きずり下ろすクジラのカルテル。毒の霧と痛みを与える戸口。そして宇宙のすべての知的存在の父祖であると主張している種族であり、ぞっとする支配者のザ・オリジナルズのこと。

しかし突然、いっそう高い音を響かせるパイプの音に、私は元いたのと同じそよ風吹く午後へと連れ戻された。

他所から来た者には、私たちの惑星のそよ風さえすごく奇妙なものでありうるというのは、とても興味深いことだ。彼はラス-dからやって来た旅行者の話もしてくれた。彼らは500年前に地球へと旅してきたが、 彼ら自身も彼らの武器や乗り物も木炭でできていたため、速やかに気流の中へと霧散してしまった。

私はオルガンの前に座って、彼のする植民地についてのおぼろな話を聞いていた。彼がシンフォニーをより大きな音で強調するときには、物語はしばらく消え、コーダになるまでとぎれ た。彼と彼の兄弟は母親のしっぽの洞の中に入り込んで、内壁からべとべとした三日月細胞を引きはがした。水分が多く柔らかくねばねばした石けんが彼らの口を漂白し、食道を下りていきながら消毒した。彼らが噛み、むしゃむしゃ食べると、それ が泡を立てた。食べ終わった後、彼らは互いにシャボン玉を吹き合った。それぞれのシャボン玉は濃い泡で満たされており、彼らはその上で眠った。そして翌朝早く、母親はしっぽを拡げてみて、彼女の赤ちゃんが黒いミートボールと甘いべとべとした泡のシチューの中で眠っているのを穏やかに見つめた。

彼はエンダートロムの味覚について詳しく物語った。彼らの鮭は、デンプン器官がパスタ料理に使われ、目はこくのあるクリームになる。それに触手のあるバターメロン。彼は子供としてデリカシーを理解しはじめたばかりで、ひと組の直立したピグミーゾウに校庭から持ち上げられていた。ゾウは空から、長いクレーンで彼の襟をつかんだ。

彼らは彼を地球に移植した。彼を乗り物から連れ出し、グランド・ラピズの町に聞こえるよう大きな音で鼻を鳴らし、それから互いに泣き合い抱き合いながら立ち去った。

「しかし奇妙なことに(エン ピシー ダー)、私は故郷の惑星で(ポン シュー)オルガンを習い、演奏(オス リー)したのです」と彼は言った。

私の娘のオルガン教師は、ここでは括弧に入れて示した余分な言葉を口にする。それが彼の母国語から来ているのか、それとも彼特有の声を出すしゃっくりなのか、誰にもわからない。彼はエンダートロムの他の遺物も持ち続けていた。彼には12の名前があっただ。

「いいえ(ウェン イス ウェン)」と彼が言った。「私が持っているのは(イン アパラ)1つの名前で(イフ)それがさまざまな言い方をされるのです」

私は朝には彼をペイジ-リーと呼び、夜にはペイジ-プロと呼ぶ。私がこれを書いているのは昼間なので、私は彼をペイジ-リーと呼ぶことにしよう。

 

つぶやきなしの耳栓

Alien at the keys.

それで私はペイジ-リーに言った。「ペイジ-リー、私は本を書いています。世界の人にRubyを教えるためです」

「おお、(ピル ノグ ピル ヨット)それはいいですね」と彼は言った。彼は私より長くRubyを知っているが、それでも娘のRuby教師になるのはだ。

「ペイジ-リー、あなたはその本に出てきますよ。あなたの惑星の話も」。私は彼がE.T.みたいな言い方をした。なぜかわからない。そしてこんなふうに言った。「いつか故郷のお父さんやお母さんの元に帰れるかもしれませんね」

それに対して彼は「(ポン シュー)(ポン シュー)(エン ピシー ダー)」と答えた。これは沈黙と畏怖をはっきり声に出す彼のやり方なのだ。

彼は私の書いたものを見たがったので、あなたのために書いたこの短いメソッドを彼に見せた。

 def wipe_mutterings_from( sentence )
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
 end

「これが何をするかわかりますか、ペイジ-リー? スモッチキスは誰でもこのメソッドを使ってあなたの話から意味不明なつぶやきを取り除くことができます」と私は言った。

そして私は彼が前に言った言葉をこのメソッドに入れてみた。

 what_he_said = "しかし奇妙なことに(エン ピシー ダー)、
   私は故郷の惑星で(ポン シュー)オルガンを習い、
   演奏(オス-リー)したのです。" 
 wipe_mutterings_from( what_he_said )
 print what_he_said

そうすると普通の文章が出てくる。

 しかし奇妙なことに、 
 私は故郷の惑星でオルガンを習い、
 演奏したのです。

「あなたはそこでWhileループを(ウェアリ トゥ)使うべきじゃありません」と彼は言った。「もっときれいで(ソプト アー)やさしいやり方があります」

wipe_mutterings_from メソッドは、基本的に開く括弧を探している。見つけると、そのあとの閉じる括弧を探す。両方とも見つかったら、それらの括弧とその中身を空の文字列で置き換える。while ループは括弧がなくなるまで続く。つぶやきがすべて取り除かれたらメソッドは終わる。

「このメソッドを見直してみると」と私は言った。「ちょっとまごつく面がありますね。もう少しうまくやれそうです」。 こんなコードを書いたことで、あなたの教師をどうか見下さないでほしい。だらしのないテクニックを見せて、一緒にそれを直していくというのもいいやり方だと思う。じゃあはじめよう。

まごつく面の第1番。このメソッドは文字列をクリーニングする。しかし間違ってファイルを渡したらどうなるだろう? あるいは数を渡したら? 何が起こるだろう? たとえばwipe_mutterings_from( 1 )とやったらどうなるか?

wipe_mutterings_from に1を渡すとRubyは以下のような出力をして終了する。

 NoMethodError: undefined method `include?' for 1:Fixnum
         from (irb):2:in `wipe_mutterings_from'
         from (irb):8

あなたが目にしているのは、幾分奇妙で冗長な(しかし時にすごく役に立つ)バックトレースと呼ばれるものだ。これは興奮した警察官で、ほんのちょっとしたトラブルの兆候にも飛んできて怪しいやつをみんな捕まえ、壁に押しつけて権利をすごく早 口で読み上げるのだが、あまりに早くて誰も聞き取れない。しかしまあ問題があるのは明らかだ。そしてもちろん、それは大きな誤解なのだ。そうだよね?

Rubyがこのミランダ権利を読み上げるときには、最初の部分を真剣に聞くようにしよう。多くの場合、最初の行にあなたが必要とするすべてがある。この最初の行が本質的なメッセージを含んでいるのだ。上の例では、最初の行は数1にはinclude?メソッドがないと言っている。前の章でreverseメソッドについて話したのを覚えている?  あのとき私は「多くのメソッドはある種の値に対してしか使えない」と言った。reverseinclude?も文字列に対しては 使えるが、数に対しては意味がなく 、使えないのだ。

わかりやすく言うと、このメソッドを数に対して使おうとしたということだ。メソッドは最初sentenceに1をセットする。それから2行目のwhile sentence.include? '('のところに来るが、数はinclude?メソッドを持たない。すばらしい。バックトレースは問題がどこにあるか 正しく示してくれている。私は誰かが数を渡してよこすなんて考えてなかったので、数に対しては使えないメソッドを使っていたのだ。

それだけのことだ。私たちのメソッドは一個の小さなポケットツールみたいなものだ。他のものには依存しない独立した道具だ。wipe_mutterings_from メソッドを使う人が数を渡すとこのパニックメッセージを見せられることになるが、それは彼らには意味をなさない。彼らはメソッドの中身を調べるようにと言われているのだが、それは本当に彼らの知ったことではないのだ。彼らはその場所は不案内なのだ。

幸い、私たちは自分のエラーを、自分の例外を投げることができる。そうして不注意に間違ったオブジェクトをクリーニングに出した人に対し、もっと意味のわかるメッセージを出 してあげることができる。

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "#{ sentence.class }からつぶやきを取り除くことはできません" 
   end
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
 end

今度は、数を渡したときに(再び1を使う)、もっと理にかなった結果が得られる。

 ArgumentError: Fixnumからつぶやきを取り除くことはできません
         from (irb):3:in `wipe_mutterings_from'
         from (irb):12

respond_to?メソッドはすごく便利だ。お願いだからこれのことを忘れないでいてほしい。respond_to?はオブジェクトを調べ 、それがあるメソッドを持っているかどうか確認する。そしてtruefalseを返す。上の例では、入ってくるsentence オブジェクトがinclude?メソッドを持つか確認している。そしてinclude?メソッドが見つからない場合に、エラーを投げている。

あなたは私がrespond_to?に対してシンボルを使ったのを不思議に思っているかもしれない。私は文字列'include?'のかわりにシンボル:include?を使った。実際、respond_to?に対してはどちらでも使えるのだ。

通常メソッドやそのほかのRubyの構成物の名前を受け渡すときにはシンボルを使う。その方が効率的だからだが、そのほうが目に付きやすいということもある。respond_to?はRubyに自分の中を見てメソッドが使えるか確認してくれと言っている。私たちはRubyに聞いているので、そのことを示すためにシンボルを使うのだ。大したことじゃない。Rubyは文字列よりもシンボルの方が早く認識できるのだ。

まごつく面の第2番。私たちのメソッドが文を変えてしまっていることに気付いた?

 something_said = "1隻の(ギス)宇宙船です。" 
 wipe_mutterings_from( something_said )
 print something_said

これ、気付いていた? 最初の行でsomething_said 変数は文字列"1隻の(ギス)宇宙船です。"を持っている。しかしメソッドを呼んだ後の3行目でsomething_said 変数をプリントしてみると、クリーニングした文字列"1隻の宇宙船です。"になっている。

どうなっているのだろう? メソッドはどうやって文字列を変えたのかしら?  変更する前に文字列をコピーしておくべきじゃないだろうか?

そう、まったくもってそうすべきだ! こんなふうに文字列を変えるのはいいマナーではない。前の章でgsubgsub!を使った。どちらが文字列を直接変更する破壊的メソッドだったか覚えている?

私たちは(このメソッドを使うかもしれないすべての善良なる人々の好意に甘えて)このメソッドをwipe_mutterings_from!と呼ぶことにするか、あるいはメソッドが元の文字列でなくコピーした文字列を使うように変えるかする必要がある。そしてこの変更は簡単にすることができるのだ! 文字列をただdup するだけでいい。

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "#{ sentence.class }からつぶやきを取り除くことはできません" 
   end
   sentence = sentence.dup
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
   sentence
 end

dup メソッドは任意のオブジェクトのコピーを行う。追加した行を見てみよう。

 sentence = sentence.dup

変なコードだ。どうやってsentencesentence のコピーになるのだろう? 自分を消しているのだろうか? もとのsentenceはどうなってしまうのか? なくなってしまうのか?

変数は単なるニックネームであるというのを思い出そう。sentence = "1隻の(ギス)宇宙船です。"でRubyは文字列を作り、その文字列にニックネームを付ける。

同様に、sentence = sentence.dupでRubyは新しい文字列を作成してそれにニックネームを付ける。これはメソッドの中で使うのに便利で、今やsentence はコピーされた新しい文字列に対するニックネームになっており、メソッドに渡された文字列を変えることなく安全に扱うことができる。

変数名が再利用されている例はたくさん目にすることになるだろう。

 x = 5
 x = x + 1
 # x は 6 になっている

 y = "Endertromb" 
 y = y.length
 # y は 10 になっている

 z = :include?
 z = "a string".respond_to? z
 # z は true になっている

そして、オブジェクトが消失する場合もある。オブジェクトが変数を通してアクセスできない場合、Rubyはあなたがそのオブジェクトにはもう用がないのだとわかり、それを削除する。Rubyは 定期的にガーベジコレクターにそういったオブジェクトを開放するように指示する。すべてのオブジェクトは、ガーベジコレクターがそれを削除するまでコンピュータのメモリ 上に存在し続ける。

そうだ、dupについてはもうひとつ言うことがある。dupできないものもあるのだ。たとえば数がそうだ。シンボル(:deathみたいな形をし たもの)はスペルが同じなら同じものになる。その点で数と同じだ。

niltruefalseのようないくつかの特殊な変数もdupできない。これらを変更することはRubyが許さない。だからコピーを作ることにそもそも意味がない。falsetrueに変えることができたらどうなるか考えてごらん。すべてが嘘になってしまう。

まごつく面の第3番は簡単なものだ。私は角カッコを文字列に対して使った。文字列を配列かハッシュのように扱った。そうすることができるのだ。文字列は[]メソッドを持っている。

角カッコが文字列に対して使われると、文字列の一部が抽出される。再びフォークリフトの角だ。文字列は長い棚で、フォークリフトが文字列の塊を引っ張り出す。

角カッコの中にはインデックスを入れる。これはフォークリフトの作業者が見えるように角の間に書かれたラベルだ。文字列に対しては、いろいろなオブジェクトがインデックスとして使える。

 str = "A string is a long shelf of letters and spaces." 
 puts str[0]       # 65 がプリントされる('A'の文字コード)
 puts str[0..-1]   # 'A string is a long shelf of letters and spaces.' がプリントされる
 puts str[1..-2]   # ' string is a long shelf of letters and spaces' がプリントされる
 puts str[1, 3]    # 'A s' がプリントされる
 puts str['shelf'] # 'shelf' がプリントされる

まごつく側面の第4番。このメソッドは無限ループに陥る可能性がある。このメソッドをハングさせて戻ってこないようにする文字列を渡すことができるのだ。メソッドを見て。泥だらけの棒を放り込んでループを詰まらせることができる?

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "#{ sentence.class }からつぶやきを取り除くことはできません" 
   end
   sentence = sentence.dup
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
   sentence
 end

ほら、この泥だらけの棒のカーブを入れると故障する。

 muddy_stick = "ここに(カーブがある。" 
 wipe_mutterings_from( muddy_stick )

なぜメソッドはハングしたのだろう? それはwhile ループが開く括弧がなくなるまでループを止めないからだ。そして開く括弧が置き換えられるのは対応する閉じる括弧があるときだけだ。だから閉じる括弧が見つからない場合には開く括弧は置換されず、while の終了条件はいつまでたっても満たされない。

メソッドをどう書き直せばいいだろう? Rubyの抜け道を知っている私は、正規表現を使うことにする。

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :gsub
     raise ArgumentError, 
       "#{ sentence.class }からつぶやきを取り除くことはできません" 
   end
   sentence.gsub( /\([-\w]+\)/, '' )
 end

ループを使うときには慎重にするようにしよう。whileループやuntilループはすぐ手に負えなくなる。イテレータを使う方がいい。そして場合によっては正規表現が使える。

まとめると、私たちがメソッドの書き方について学んだのは:

  1. メソッドを使う人が予期してないようなものを渡してきても驚かないようにしよう。彼らのよこしたものがまったく使えないなら、エラーをraiseすればいい。
  2. メソッドが渡されたオブジェクトを変更するのはエチケットに反する。dupでコピーを作ろう。あるいはgsub のような自動的にコピーを作るメソッドを使ってもいい。
  3. ArrayHashStringのオブジェクトは[]メソッドを持っており、中にあるものを探すのに角カッコメソッドが使える。また、これらのオブジェクトは[]=メソッドも持っているので、角カッコ を代入文(の等号の左辺)で使って中身を書き換えることができる。
  4. 手に負えないループに気をつけること。可能であればwhileuntilを避ける。

 

呼び名のメカニズム

Cat salesmen from the sky.

ペイジ-リーの家の裏の木がガサガサという音を立て、それは空から男が降ってきたためだとわかった。彼は名をダグと言い、猫を売っていた。

彼が視界に入ると、彼の影(と彼の足にくくりつけられた猫の影)が、私たちがラケットボールで撃とうとしていた芝生の鳥を隠した。大きな風船からヘリウムを絞り出している彼に、私たちは「こんにちは、ダグ!」と叫んだ。

すると彼は「こんにちは、ゴンク-リー! こんにちは、ホワイ!」と答えた。

ペイジ-リーはポケットを調べ、1ドル27セントあるのを確かめた。暖炉の番と衛星放送アンテナの向きを変える仕事に必要な3匹の猫を買うためだ。ペイジ-リーが猫たちをジェネレーターに放り込むとひと しきり文句を言ったが、たくさんある巨大なガラス棒が猫たちを絶えず愛撫するだろう——でも待って、猫商人は彼をゴンク-リーと呼ばなかった?

そして彼は朝にはゴンク-リーと呼び、夜にはゴンク-プロと呼んだ。

だからサフィックスは昼夜と関係があるに違いない。私にわかる限りでは、プレフィックスの方は呼ぶ人のペイジ-リーに対する関係を表すようだ。

 class String

   # 娘のオルガン教師の名前のパーツ
   @@syllables = [
     { 'Paij' => '私用',
       'Gonk' => '仕事',
       'Blon' => '奴隷',
       'Stro' => '主人',
       'Wert' => '',
       'Onnn' => '' },
     { 'ree'  => '午前',
       'plo'  => '午後' }
   ]

   # 彼の名前が何を意味するか判断するメソッド
   def name_significance
     parts = self.split( '-' )
     syllables = @@syllables.dup
     signif = parts.collect do |p|
       syllables.shift[p]
     end
     signif.join( ' ' )
   end

 end

私は単にだらしのないコードを見せるというのを越えてしまった。これははなはだ不作法であり、自然に対する罪だ。ほとんどの言語はそもそも犯すことを許していないような罪だ。私たちはRubyのコアのクラスの1つであるStringを変更しているのだ!

「これがちょっと危険なことはわかっています」ペイジ・リーの鼻先にこのコードを差し出したとき、私はそう言った。「これで困る人がいないといいのですが」

「スモッチキスはみんなこれがどんな危険をもたらすか(ケプ ヨ イコ)味わうべきです」と彼は言った。「犬に、丸太に、沼へのはまり込み(クル イプ)、すべて味わうべきです」。そして彼はビーグルベリー沼地ドリンクをぐいっと飲んだ。

String クラスに追加するとはどういうことなのか? 2つある。クラス変数、それにメソッド。普通のインスタンスメソッドだ。

私はアットマークをアトリビュートを意味する文字だと思うようにしている。二重のアットアトリビュート・オールを意味 する。クラス変数だ。クラスのすべてのインスタンスはこの変数を見ることができ、値はどのインスタンスにも同じになる。@@syllables変数は配列で、今やStringクラスの中ならどこでも使えるようになった。

新しく作ったメソッドのname_significanceは、どんな文字列に対しても使える。

print "Paij-ree".name_significance 私用 午前とプリントされる。

これにより、ペイジ・リーは私的な名前であることがわかる。友達が早い時間に使う名前だ。

selfを使っている行を注意して見てほしい。これは特殊変数で、メソッドの呼ばれている対象のオブジェクトを表している。 わかりやすくするため、ハイフンで文字列を分割するメソッドを作ってみることにしよう。

 class String
   def dash_split
     self.split( '-' )
   end
 end

このメソッドもまた、すべての文字列に対して使えるようになる。

"Gonk-plo".dash_split は配列['Gonk', 'plo']を返す。

self の使用はRubyのより進んだ概念へと入りはじめたことのしるしだ。Rubyは定義言語だ。あなたはメソッドを、それが使われる前に定義ずる。そのメソッドを使うオブジェクトの存在を準備しているのだ。 ここであなたは「dash_splitが使われるときには、ハイフンで分割しようとしている文字列が あるわけだが、self はその文字列を参照する特殊変数だ」と言っているのだ。

Rubyはすごい定義言語だ。この本を深く読み進めていけば、興味深く頭を悩ませる議論が出てくる。

多くの場合にはself を明示的に使う必要はない。メソッドは他のメソッド定義の中から直接呼び出すことができるからだ。

 class String
   def dash_split; split( '-' ); end
 end

name_significanceメソッドにあるループを見つけてごらん。Array#collectについて学ぶことはとても重要だ。詳しく見てみよう。

 signif = parts.collect do |p|
   syllables.shift[p]
 end

配列partsは分離された名前を持っている。たとえば['Paij', 'plo']のような。この配列のそれぞれの要素をcollectを使ってイテレートするのだが、collecteachより進んでいる。eachと同様に、collectはそれぞれの要素をブロック引数として滑り台で落とす。それから、ブロックの終わりで、collectブロックが返す答えを取っておいて新しい配列の中に追加していくcollect メソッドは既存の配列の値に基づいて新しい配列を作るためのすばらしい方法だ。

ダグは売り物の猫を3匹持っている。1匹は12セント、別な1匹は63セント、最後の1匹は9セントだ。20%チップをつけるとしたら、それぞれの猫がいくらになるか見てみよう。

 catsandtips = [0.12, 0.63, 0.09].collect { |catcost| catcost + ( catcost * 0.20 ) }
  (猫とチップ)                                   (猫代)

ペイジ-リーの家の敷地は森のとてもすばらしい場所にあると思う(猫やダグが降ってこないときには)。よくペイジ-リーと私は家の裏にある川の側にテントを張ってキャンプし、薫製のブラックバードを食べ、小さな眠るインディアンの像を薄暗い光の中で彫った。時折彼はスペードで負け、彼がエンダートロムのことを思い出して集中していないのがわかった。このすべてがときどき彼を揺り動かしていたに違いない。私は彼の話を聞く最初の人間だった。

「私はアンブローズから来たばかりです」と私言った。「地下の我が家のような場所で、エルフが動物を完全なものにしようと努力しています」

彼はもごもご言いながらうなずいた。「あなたはそのような(ポス イン オイン)ことに関わって(イン)はいけません」

「私たちが失敗すると思いますか?」

「私は(プリープ)以前そこにいました」と彼は言った。それからくじの話をした。

4. ヤギは映画を全部見たがっている

Blinky, winky, a goat... awakes...

「こんにちは??
何か学べる相手は誰かいませんか??」

「エレベーター?・・・
・・・まさか・・・
エ・エ・エレ・レベーター・・・
・・・ありえない・・・
・・・エレ・・・
いや・・・」

 

エレベータが開くと、棚やファイルキャビネットがたくさんある緑色の部屋に出た。テープのリールやフィルム缶やビデオテープがそこら中にあった。ドクター・チャムにはその多くが何なのか見当も付かなかった。彼が目にしたのは、大きな未来的な混乱だった。

幅の狭い棚の列に躓きながら、彼はもう一度声を上げた。「すいませーん。知的生命を探してるんですが? 私は宇宙旅行者です!」。彼は足をビデオデッキのスロットに突っ込んで転んだ。「コミュニケートできる存在は他にいませんか?」

彼は手のひらをメガホンにして叫んだ。「すいませーん」

「大声で叫んでいる」。眠たげなヤギがとぼとぼとやってきた。

The goat already knows Dr. Cham.

「いい出だしだ! 
このかなたなる世界でヤギとは!」
「落ち着いてよ」

「私がここにいるだろうことは知っていただろう。君はあの本を読んだのだから。このことについては書かれている。私もあの本は読んだのだ。私は君がやりすぎることを知っている。私は君にそれをやめるよう頼む」

「私たちは最高の友達だ! すばらしい2人だ!」
「しかし本が終わったら、私は君を食べる!」

「あの本は嫌いだ」とヤギが言った。「著者は不誠実なのに違いない」

「ほんとに?」とドクター・チャムは聞いた。

「あれがすべて正しいのは確かだ。ただひどく潤色されている。私は読んでいて、もういい、わかった、いい加減にやめろ、と思う」

「私には良くわからない」とドクターは言った。「誠実な労作のように見えるけど。実際私は向こうでRubyを書いたんだ」

「あの本はヤギにちゃんと名前も付けていないんだ」とヤギが言った。

「しかし君はあの本に出てくる唯一のヤギだ」とドクターが言った。

「私はまったく誤って描かれている」

The mechanics behind devouring Dr. Cham.

「私たちはこんなに仲のいい友達なのに、本当に私を食べるの?」
「髭は食べないがね」

「しかしどうしたら食べられるんだ? 君はそんなに小さいし、君の口は小さすぎる・・・」
「ちょっとだけ・・・」

「ウワーッ」

ヤギは口を閉じ、ドクター・チャムは胸を押さえた。

「私は実際文学にとても詳しいんだ」とヤギが言った。「もっとも最近は映画に切り替えたがね。外国映画が好きなんだ。親戚がちょうど君の惑星から「イシュタール」を持ち帰っ てくれたところなんだけど、あれは素晴らしい映画だ」

「私は自分の惑星を長いこと留守にしている。今となってはそれを故郷と思うことさえ難しい」

「ウォーレン・ビーティがいい。彼の役は基本的に社会的に駄目な人間だ。彼は自殺しようとするが、ダスティン・ホフマンが窓枠に座って、このまったく陽気で悲痛な歌を歌い叫ぶんだ 。ここにあるから見てみてよ」

「何か食べるものはない?」とドクターは聞いた。彼はまだ落ち着かなかった。

「映画を見ながら触手のあるバターメロンを食べるのはどう?」とヤギが言った。

それで2人はヤギのプロジェクターの方へと戻った。冷凍貯蔵室から戻ると、大きな絨毯の上に座り、凍らせたバターメロンの付属物を折り取った。殻は固かったが、割ると中にはコクのあるクリームがたっぷりあった。味は甘く、といもいい香りがした。

「君が見るべき最初の映画は地元で撮影と制作が行われたものだ。私はキャスティングをした女性と親しい友達だ。しばらく付き合っていたこともある。キャストが発表されるずっと前からそれぞれの役を誰がするのかみんな知っていた」

ヤギはドクター・チャムにプロジェクターをセットさせた。「音楽はサラウンドになっている。君はノブを受け持ってくれ」

 

フィルムストリップのノブを回すと、ドクター・チャムはヤギと一緒に見始めた。サウンドトラックがうるさい溶岩と風とトランペットの音を響かせた。

「ザ・オリジナルズ」

フィルムストリップはオリジナルズと呼ばれるこの動物たちで始まる。彼らは最初の生物だと主張していた。

「我々はNo.1だ!」
「お前の頭はひどいな」

実際、彼らはかつて存在したすべての中で自分たちが最初だと主張していた。

そうでない証拠を持っていなかったのがその理由だ。彼らの惑星の周りは真っ暗闇で、本当に遠くにある1つの星か何かがわずかな銀色の光を発していたにすぎない。

 

彼らは原始的だったが、どうにか赤外線灯を発明し、最初のアボガドを育てた。

しかし彼らはバケツをまだ持っていなかったため、川の水を口に含んで植物のところまで運ぶ必要があった。

「我々が知る必要のある数はNo.1だけだ」

そして彼らは知性も、どのような種類の規律も欠いていたので、大学に通うことも大物になることもなかった。

「お前はトースト男みたいだ」

彼らは価値がなかったかもしれない。彼らは生きているべきではなかったのかもしれない。彼らはただ非常に単純だったのだと私は考えている。

 

時が経つとともに、暗闇が薄れ、他の惑星が見えるようになった。

 

そして新しい動物たちが彼らの惑星にとても長いはしごのある宇宙船に乗ってやってきた。

「議会は改正せよ!!」

新しい動物たちは自分の町を作り、みんなに投票を呼びかけた。

「出て行け!」
「ああ、お前はクズだ」

しかしオリジナルズはこれらのエイリアンたちに好きにさせなかった。そして彼らが心の狭い批難の挙に出たというのは残念なことだ。

映画のこの時点、動物の開拓民の2つの群れの間に起きた地上戦のところで、ドクター・チャムの心はさまよいだした。彼らの戦いと作戦の詳細は、ドクター・チャムがプロジェクターに入れた透明なフィルムのスプールの最後まで ずっと続いた。

戦いに次ぐ戦い。「エルマー湖の包囲」。「ニュートン・P・ジラフと息子たちの最後の抵抗」。「小さな見捨てられた群れへの犬の侵攻」。これらの戦いで死んだ動物はいなかった。多くの場合、攻撃は他の動物の頭をひっぱたくことからなっていた。それから互いの鼻をつまみ合 うのだ。しかしこれは、本当に、すごい辱めなのだ。

恥ずかしさの叫びが上がった。それは十分機能しているようだった。

 

オブジェクトの誕生

「心配しないで」ドクター・チャムの注意を映画に引き戻そうとしてヤギが言った。「うまく行くよ」

RubyではObject がすべての中心にある。それはオリジナルなのだ。

 class ToastyBear < Object; end

小なりの記号は継承を表している。つまり新しいToastyBear(トーストみたいなクマ)クラスはObject をベースにした新しいクラスということだ。Object の持つメソッドはすべてToastyBearでも使える。Object の定数はToastyBearでも使える。

しかしすべてのオブジェクトはObjectを継承している。このように書いても・・・

 class ToastyBear; end

こう書くのと同じことになる・・・

 class ToastyBear < Object; end

継承は便利だ。互いに関連のあるオブジェクトの種族を作ることができる。問題を分析しているときに、共通の属性を持ついろいろなオブジェクトを見つけることだろう。問題の一部をすでに解いているクラスから継承することで、労力を節約することができる。

あなたがアメリカに住んでいる人の番地、市、州、郵便番号を保存するためのUnitedStatesAddress クラスを持っているとしよう。イギリスの住所を保存するようになって、UnitedKingdomAddress クラスを追加する。この住所を表す2つのクラスがAddressクラスを継承するようにすれば、どんな住所も扱える郵便ソフトウェアをデザインすることができる。

 def mail_them_a_kit( address )
   unless address.is_a? Address
     raise ArgumentError, "Addressオブジェクトが見つかりません。" 
   end
   print address.formatted
 end

継承はクラスのある振る舞いを上書きしたい場合にも優れた方法だ。たとえば普通のと少し違った自分のArray クラスがほしいとしよう。あなたはjoin メソッドを変更したい。しかしArray#joinを直接変えると、Arrayを使っている他のクラスに影響を与えることになる。

だからオリジナルのArrayをベースにしてArrayMineという自分のクラスを書くことにする。

 class ArrayMine < Array
   # この配列から1つの文字列を作る。それぞれの要素を指定した書式で整形し、それからつなぎ合わせる。
   def join( sep = $,, format = "%s" )
     collect do |item|
       sprintf( format, item )
     end.join( sep )
   end
 end

ArrayMineは独自のjoin メソッドを持つカスタマイズされたArray クラスだ。ArrayArrayMineスーパークラスだ。すべてのオブジェクトは、この関連を確認できるsuperclassメソッドを持つ。

 irb> ArrayMine.superclass
   => Array

完璧だ。私たちはホテルを経営していて、部屋のサイズのArray を持っている: [3, 4, 6]。これをパンフレットにきれいに印刷することにしよう。

 rooms = ArrayMine[3, 4, 6]
 print rooms.join( "", "%dベッド" ) + "の部屋をご用意しております。"

これは「3ベッド、4ベッド、6ベッドの部屋をご用意しております。」とプリントする。

ドクター・チャムはトイレを探したが、どこもかしこも保存用のビデオテープだらけだった。彼はようやくトイレだったらしい場所を見つけた。そこには金属製の容器があった。さらに重要な のは、それが暗く、視界の遮られる場所にあったということだ。

彼が用を足している間に、オリジナルズは最初の生き物としての権利を守るために侵略者たちを虐殺したが、RubyのObjectはそのような争いは一切しないと いうことを説明しておこう。Objectは疑う余地のない王、オブジェクト一世なのだ。

見てごらん。

 irb> Class.superclass
   => Module
 irb> Kernel.class
   => Module
 irb> Module.superclass
   => Object
 irb> Object.superclass
   => nil

ClassでさえObjectなのだ! クラスはオブジェクトを定義する言語ではあるが、そのクラスメソッドを呼び出してオブジェクトのように扱うこともあるのだ。目の回る循環のように見えるかもしれないが、これは厳格な親子関係だ。そしてObjectを変えるときには、Rubyにあるすべてのものを変えることになる。これはあり得ないくらい恐ろしく、万能で、大変動をもたらす、すごいことだ!  Rubyは何も制限しないのだ、姉妹よ、兄弟よ!

ClassObjectの間にModuleがあるのに気付いた? Objectが王で、Rubyの他のすべての父祖だとすると、Module は貧しい孤児たちの修道女で、Rubyの街の子どもたちを守り、保護している。(アナロジーを完成させるなら、Class は村の学校の先生で、Kernelは尊大な村の顔役だ。)

Moduleの存在の要点はコードに食べ物と住む場所を与えることだ。メソッドはModuleのショールの下で雨に濡れずに済む。Moduleはどんな種類のクラス、定数、変数でも持つことができる。

「しかしモジュールは何をするの?」と聞くかもしれない。「どんな仕事をしているの??」

「モジュールのすることはそれで全部だ!!」と私は言い返し、無益さの最大の表現として開いた手のひらを伸ばす。「よく聞いて——二度は言わないから——モジュール修道院長は、哀れなオブジェクトたちに住み家を与えるのだ!!」

 # これがモジュールだ -- 私たちのコードを他のどこに置けるっていうの? (気を配る聖アグネスモジュール)
 module WatchfulSaintAgnes  

   # 定数は戸口の近くにいる。結構。(フォークを持った歯なしの男定数)
   TOOTHLESS_MAN_WITH_FORK = ['', 'フォーク', '露出した歯茎']

   # クラスはキッチンの中で快適に食べ暮らしている。(太った青白い子供クラス)
   class FatWaxyChild; end

   # メソッドはバナナクローゼットの裏に隠れている。理由は神のみぞ知る。(内気なキツネ顔の少女メソッド)
   def timid_foxfaced_girl; {'お願い' => 'ドングリをください'}; end 

 end

聖アグネスのところを見て回って、彼らを見つけ出そう。

 >> WatchfulSaintAgnes::TOOTHLESS_MAN_WITH_FORK
 => ["", "フォーク", "露出した歯茎"]
 >> WatchfulSaintAgnes::FatWaxyChild.new
 => #<WatchfulSaintAgnes::FatWaxyChild:0xb7d2ad78>
 >> WatchfulSaintAgnes::instance_methods
 => ["timid_foxfaced_girl"]

Module が宿に過ぎないということをいつも忘れないようにしよう。頭の上の屋根だ。自意識のあるClass ではなく、newで命を与えることもできない。

 >> WatchfulSaintAgnes.new
 NoMethodError: undefined method `new' for WatchfulSaintAgnes:Module
         from (irb):2

聖アグネスは、希望のないコードたちの世話をするために一生を捧げたのだ。どうかそれを取り上げないでほしい。

でも聖アグネスから盗もうというなら、お手伝いしよう。もっと大きな修道院を持ってきてWatchfulSaintAgnesを飲み込んだら、彼女には何が残るだろう?

それにはextendが使える。これはモジュールのすべてのメソッドをクラスかオブジェクトに取り込むことができる。

 >> class TheTimeWarnerAolCitibankCaringAndLovingFacility; end
          (タイムワーナーAOLCityBankの愛と福祉の施設)
 >> TheTimeWarnerAolCitibankCaringAndLovingFacility.extend WatchfulSaintAgnes
 >> TheTimeWarnerAolCitibankCaringAndLovingFacility::instance_methods
 => ["timid_foxfaced_girl"]

本当を言えば、誰もWatchfulSaintAgnesから盗むことはできず、ただ借りるだけだ。timid_foxfaced_girl はいまや2つのアドレスを持つようになったのだ。

認めなきゃいけない。古い修道院を何度買収したところで、あのキツネ顔の小さな女の子は相変わらずバナナクローゼットに隠れてドングリを欲しがっている! 彼女に食べ物をあげられないのは残念なことだ。彼女は引数なしのメソッドなのだ。

ドクター・チャムがすっきりして出てきたとき、フィルムはちょっとつまらなかった。ヤギが気付いていなかったので、ドクターは意味があるところまでフィルムを進めた。

 

そして生き物たちみんなが戦争になった。それは健康の本に書いてある、体の中で脂質とアミノ酸が繰り広げる戦いみたいだった。

それはつまり、彼らがしばしばコルモみたいなつまらないものをめぐって戦ったということだ。コルモというのは、人気のあるツナサンドイッチのブランドだ。

レモン + スプーン
34.00ドル

そしてレモンセットの値段は高かった。

そこへ2匹のヤギが現れ、自分たちはどっち側だったかと聞いた。どちらも覚えていなかったのだ。

 

オリジナルズはたぶんヤギは自分たちの側だと思った。ヤギがいたような気がする。いたよね? しかし・・・

侵略者は自分たちがヤギを連れてきたのだと断言したのだ!!

「お前ら遅いぞ!」と彼らは言った。

しかしこれには裏があった。ヤギの一匹はオリジナルで、もう一匹はそうでなかったのだが、彼らは愛し合っていて、嘘をついたのだ。

(ええ、この者たちはドクター・チャムの友達ですっかり心を奪われたヤギの親です。)

 

「もしかすると」とヤギたちは言った。「我々は間違った惑星にいるのかもしれない。この惑星は年取りすぎなようだ」

「ここは最古の惑星だ!」

「それは確か?」

侵略者たちはオリジナルズが最初の動物であるというのを信じていなかった・・・彼らの惑星が最古だというのも・・・

それでも彼らは、その惑星がどれほど老いているか見るようになった。

そして侵略者はこの惑星を去った。

「この惑星は老いている」とドクター・チャムは言った。「城は素敵だが、中はひどいものだ」

「城の見かけは映像だ」とヤギが言った。「花やリンゴの花や空さえもそうだ。低解像度の投影像なのだ」

「ほんと? すごく魅力的だけど」

「たぶんそうだ」

 The spool ends.

動物たちは偶然ピープルマッドと呼ばれる惑星を発見した(ドクター・チャムは、自身の旅からその惑星が どこか分った——それはまさに彼が後にした惑星だった。)

彼らはそこに住むために降り立った・・・しかし動物たちの口から一斉に血が噴き出した・・・

ブルーーシュシュシュ

・・・そして大きなタマゴの黄身が画面中にあふれる・・・

「うわっ、何だ!」

「めちゃめちゃだ!」とヤギが言った。「映画はこんな終わり方じゃない! 血は出ないはずだ! 何があったんだ? 一体何が? ノブを壊したんじゃないか?」

「わからない」とドクター・チャムが言った。ノブを前に後ろに動かし、レンズを叩いてみた。

「フィルムを調べて! フィルムを!」

ドクター・チャムはプロジェクタからフィルムを取り出してみると、端が溶けていた。

「なんてことだ! このプロジェクタは高級品なんだ! こんなこと一度もなかった。ありえない」

 

声の探索

「プロジェクタのせいだとは思わない」とドクター・チャムが言った。「何かがスクリーンを飛びすぎて、痛烈な呻きをあげたのだ」

「私はあの映画に出ていたばかとは違うぞ」とヤギは陰気に言った。「そしてあの少女。あのキャスティングディレクター。彼女とはもう会っていない」

ドクター・チャムは立ち上がってテープの山を見渡し、探した。

「ああ、そうだ、君はあの少女を呼ぶべきだ」とヤギが続けた。「彼女と話して理解を求めろ。私のことを話してくれ。私の友達でないような振りをするんだ。わたるだろう、『ああ、あいつか? まったくのバカさ』」

ドクター・チャムは戸口を見つけて外に出た。

廊下はまったく別な混乱した世界だった。ヤギの保管庫の中の棚は散らかっていたが、廊下では棚がすっかり倒れていた。流しが天井を突き抜けて落ちていた。ドクターは瓦礫の中を、必要なときにはベニヤ板を蹴りながら進んだ。

「君はここを出るべきじゃない」とヤギが言った。「君がいるのは他の人の私有地だ。ここのものはすべて2頭のピグミー象が所有している。いやな連中だ。彼らはあの鼻で君 をたたき出すぞ。彼らはそれを台無しにして君をぶったたくだろう」

ドクター・チャムは行く手にあるファイルキャビネットを押すと、それはもろい壁ごと倒れて、隣の部屋の床を抜けて落ちた。彼らはそれがいくつかの床を突き抜けて落ちるのを聞いた。

「私は本の中でどうなったのか思い出そうとしている」とドクター・チャムはホールを足早に歩きながら言った。「白い霧が投影をよぎった。私たちはあれを見つけたのだ」。彼 がドアノブをガチャガチャ動かすと壊れて取れたのでドアを蹴破り、中に消えていった。

「君はほんとはものを壊して楽しんでるんじゃないか?」とヤギは言った。「壁にドアだ」。ヤギは壁に頭突きした。壁は震え、それから倒れた。

そして静かになった。そして真っ暗に。

ヤギは荒涼とした廊下にじっとしていた。ドクター・チャムが机をひっくり返しながら現れて、彼が押し入った部屋から先に進む準備ができたと言うのを期待した。しかしドクター・チャムは戻ってこなかった。ヤギ は彼の周りに残された瓦礫とともに時を共有することにした。彼は何も見ることができなかった。ただ時折脚を動かしたときに送り状やカーボンコピーや茶封筒の山がガサガサ音をたてるだけだった。

地面がヤギの下でよじれているように、彼の周りでさざなみの山が彼の重みの方へ滑ってくるように思えた。彼は象のドキュメントの渦の中心にいた。彼は紙による切り傷で死ぬのだろうか? あるいはオフィス用品にうずもれて窒息するのだろうか?

やわらかい光が彼に近づいてきた。浮かんでいる銀の魚。いや、あれは——はさみ? はさみはかすかに光る知的なパンの群れになり、それぞれのスライスが光にむせていた。いや、しかしそれは手だった。それにイースターハットだ。

The goat alone in the hallway, meets an apparition.

「メープルドーナツは持っている?」
「君は誰?」

「へー、君の肌は薄れているね」
「死んでるから。私は死んでるし、服も死んでるの」

「死んでる?
これはいい! 私は大きな口であいつをおどかしてやったけど、今度は君の死んでいることでおどかしてやれる
——やつの神経は飛び上がるに違いない!!」

別な部屋では、ドクター・チャムが透明なガラスの下に静かに立っていた。天井が突然透明になり、彼のズボンやジャケットが星の光に洗われた。美術館で箱に納められた古い写本のようにやわらかい光で照らされたぼやけた色の部屋の中心に彼は歩を進めた。床を横切って進むにつれ、より多くの星、より多くの綿の塊のような火が姿を現した。そしてすぐにそれが視野に入った。彼はそれがもっと大きいものと思っていたが、そうではなかった。

地球。色を付けた卵のように、まだ新しい。彼は長いチェロの弦が背骨の中で鳴るのを感じた。どうしてあれがピープルマッドと呼べる? 活気があり草に覆われた電球だ。何かがそれに向かいつつある、1つの大きなボール。

彼はあのロケットのことを考えた。実際、彼はあのロケットを逃した。すごいダンサーの一団。彼はロケットを見たとき、それに対して何か叫んだ。何かとても鋭く有望なことを。

そう、ロケットが手に手を取って回転したとき、彼は叫んだのだ。「同心円!」 それは他の誰もわざわざ観察しようとしないものだ。

そしてこの考えはドクター・チャムの優越感を満たすのに十分だった。彼は戻りながら間の抜けた笑みを浮かべていた。彼は彼の天才がそのような陳述を通して現れるのを感じた。円の単純さを認識する者は自分だ。彼は廊下に戻る間、ずっとそのことを考えていた。

私はそれをすごいと思う。時間があれば自分をあがめるのだ。

The Doctor knows this ghost.

「うわ、なんてことだ! 死んだ女の子がいる!」

「あれは死んだ姪のハンナだ。ハンナ、ヤギさんを1人にしてあげなさい」

「メープルドーナツを私にくれないとだめよ! 

「お前は私の目の中のメープルドーナツだ」

「ああ、そうだ」とヤギが言った。「君の姪だ。君が殺した姪だ。今や君と同意見だ」

ほんのしばらくの間、彼らは互いに見詰め合っていた。ドクター・チャムとヤギが「ああ、ハンナはトラブルを引き起こしてくれるぞ。彼女はすでにメープルドーナツのことを言っている」と考えるのに十分な くらいの間。

「彼女はこんな風にメープルドーナツのことをすぐに話し出すのか?」とヤギは聞いた。

「ああ、そうだ」とドクター。「彼女は君に言い、それから私に言う。彼女はどこかでメープルドーナツを見るんだ——それがどこなのか思い出せない」

「私は本物のメープルドーナツを見るの?」とハンナが聞いた。「私は本物が必要なの」

「そうか、そうか」とヤギが言った。「ああ、思い出したよ。本物のメープルドーナツを見たら、本物の人間に戻れると彼女がここで言うんだ。彼女の本来の運命は自分のパン屋を持つことだったのだが、君がその運命をぶち壊し、彼女は幽霊の状態に囚われているというわけだ」

「ええ、その通りよ!」ハンナが叫んだ。

「この場面を再び耐えなければならないというのはひどいことだ」とドクターが言った。「ドーナツは取るに足らない。ほうっておくことだ」

「この章を思い出すのに苦労している」とヤギが言った。「この広間を出る方法すら思い出せない。私はあの本を30回は読んだはずなのだが。壁を破るんだったかな? それとも誰かが見つけてくれるまで叫ぶんだったか?」

「ハンナが浮遊して壁を通り抜け、ある機械を見つけるんだ」とドクターが言った。「私はプログラムを書く必要がある——それがどうかしてうまくいくんだ」

「しかし私の言うことが分かるだろう?」とヤギが言った。「私は細かいことを全部忘れてしまった。特に前の方の章は。エンディングは完全に思い出せる。終わりまでじっとしているのはつらいな。最後はずっと良くなる」

ドクター・チャムは腕組みして踵でシーソーしている。「あのヤマアラシ」。彼はヤギに向かって貪欲な笑みを見せた。

「まったく。あのヤマアラシにはぜひとも会いたいね」とヤギが言った。「本が終わったら彼があの金で何をするのか興味あるよ」

ドクター・チャムは恭しくうなずいた。「彼がスリッパを履いているのを見たときは興奮したね」

「まったくあのひどいスリッパ!」ヤギは言って、粗野に笑い、つばがあごから滝のように流れた。

このナンセンスが途絶えるのを待ちながら、ハンナの心はガタガタ震えてていた。彼女が頭を傾けると、ガタガタは頭蓋の曲線に沿って動いた。 彼女の後頭部が消え(彼女の言い方だと、溶解し)て小さなノイズが途絶えたが、頭が戻ってくるのとともに小さなガタガタも戻ってきて、気づくと再び無頓着なうめきをあげていた。ホオオオオ ルゥオオ オオオオ オオオオ。

「私はchunky baconというのにはハマっていない」とヤギが言った。「あれのどこがそんなにすごいのかわからない」

彼女はうめきながら話すことはできたのだろうか? ボン ボン。フランス語のうめき。ボォン ボォン。ン ナペ ティート ウオオオオ オオオオ

「彼女に害がないのは分かっているが、あの音には頭がおかしくなりそうになる。髪がすっかり逆立っているよ」

「ハンナ?」ドクター・チャムが言った。「どこにいるんだ、お嬢ちゃん? どうかいい子にしておくれ」

彼女は彼らのすぐ近くを出たり入ったりしていた。そして彼女が咳払いし、明るく、星屑を撒き散らす天使のように話すのを聞くことができた。そう、メープルドーナツの話 がまるまる再び現れ、さらに彼女が持つはずのパン屋と、マフィンにロールパンにバゲットについての話が現れた。

5. 盗まれたくじ主

The piping and mixtures of the lotteries.

さて、ペイジ-リーのくじの話だ。

エンダートロムでは、オルガン奏者の父親がくじを発明した。彼はそのアイデアを、ディガー・ドシュに祈っているときに思いついた。

ディガー・ドシュというのは一種の神のようなものだ。しかしその10倍も恐ろしい。この男は惑星を貫く限りなく深いトンネルを掘り、死人になって出てくる。しかし本当に死んでいるわけではない。彼は死の1秒前にいる。そして彼は時間を食べているのだ。

ディガー・ドシュは人々を殺すので話はちょっと込み入っているのだが、彼の言うとおりにしていればそんなに悪いことにはならない。たぶんそのことについては後で話す。 すごく恐ろしくて話すのがとても辛いのだが、私の友達の1人は実際まるまる信じ込んだ。私は息が詰まりそうになった——叫ぶ というより窒息しているみたいだった。

何にしても、あるときペイジ・リーの父親がお祈りをしていると、3つの数字が現れた。

彼は心の中で思った。「この数字はなんだ?」

そして彼の心は彼があらゆる数字を売っている短いビデオクリップを再生した。何年も旅をして、数字を売っているのだ。

それで彼は自分の頭に尋ねてみた。「人々は数字を買うものだろうか?」

彼の頭の答えは「正しい数字を3つ買ったら、賞品をあげるのだ」

それに対し、自分がスキージャンプで飛び出して、人々にプレゼントを雨と降らせているところを想像した。疑いなく、彼は偶像になるだろう。

それで彼は頭の言うとおりに数字を売ることにした。この父親の単純なくじは、25個の数字から違う数字を3つ選ぶというものだった。

 class LotteryTicket

   NUMERIC_RANGE = 1..25

   attr_reader :picks, :purchased

   def initialize( *picks )
     if picks.length != 3
       raise ArgumentError, "数字を3つ選んでください" 
     elsif picks.uniq.length != 3
       raise ArgumentError, "3つの数字は違うものでなければなりません" 
     elsif picks.detect { |p| not NUMERIC_RANGE === p }
       raise ArgumentError, "3つの数字は1から25の間でなければなりません" 
     end
     @picks = picks
     @purchased = Time.now
   end

 end

LotteryTicketクラスは、3つの数字 (@picks) とチケットが購入された時刻 (@purchased)を持っている。数字の範囲(1から25)は、定数NUMERIC_RANGEに保持される。

initialize メソッドに渡される引数はいくつあってもいい。picks 引数のアスタリスク渡される引数が配列であることを意味している。引数が配列であるため、その引数に対してuniqdetectのようなメソッドが使える。

このクラスは2つの定義を含んでいる。メソッド定義 (def)と属性定義(attr_reader)だ。実際のところ、どちらもメソッド定義なのだが。

attr_reader は以下のようにRubyコードを書くことのショートカットになっている。

 class LotteryTicket
   def picks; @picks; end
   def purchased; @purchased; end
 end

属性は(@picksのような)インスタンス変数のラッパーメソッドで、クラスの外から使うことができる。ペイジ-リーの父親はチケットから数字と日付を読み取る機械のプログラムを書きたかった。そうするためには、これらのインスタンス変数 が公開されている必要がある。

ランダムなチケットを作って、その数字を読んでみよう。

 ticket = LotteryTicket.new( rand( 25 ) + 1,
             rand( 25 ) + 1, rand( 25 ) + 1 )
 p ticket.picks

これを実行したら、[23, 14, 20]となった。もし2つの乱数がたまたま同じだとエラーになる。

チケットの数字をクラスの外から変えることはできない。

 ticket.picks = [2, 6, 19]

これはundefined method `picks='というエラーになる。attr_readerリーダーメソッドだけを付け加え、ライターメソッドは付け加えないためだ。しかしこれはこれでいい。私たちはチケットの数字や日付を変えられたくはない。

チケットはオブジェクトだ。LotteryTicket クラスのインスタンスだ。チケットを作るにはLotteryTicket.new とやる。それぞれのチケットは、固有のインスタンス変数@picks@purchased を持つ。

くじ主は、くじを締め切ってから3つの乱数を選ぶ必要がある。だからランダムなチケットを生成する便利なクラスメソッドを追加することにしよう。

 class LotteryTicket
   def self.new_random
     new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
   end
 end

おっと、2つの乱数がたまたま同じだと間抜けなエラーが出る。数字が同じだとinitializeArgumentError投げるのだ。

エラーが起きたときはメソッドをやり直すことにしよう。Rubyのrescueでエラーを処理し、redoでメソッドを始めからやり直すようにできる。

 class LotteryTicket
   def self.new_random
     new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
   rescue ArgumentError
     redo
   end
 end

良くなった。ちゃんと数字を選ぶのに何回かやり直す必要があるかもしれないが、最後にはうまく行く。待っているのはワクワクしない?

くじ主はチケットを買った人を、引いた数字と合わせて記録しておく。

 class LotteryDraw
   @@tickets = {}
   def LotteryDraw.buy( customer, *tickets )
     unless @@tickets.has_key?( customer )
       @@tickets[customer] = []
     end
     @@tickets[customer] += tickets
   end
 end

ヤル-ダル-リップ-シップが最初の客だった。

 LotteryDraw.buy 'ヤル-ダル-リップ-シップ',
     LotteryTicket.new( 12, 6, 19 ),
     LotteryTicket.new( 5, 1, 3 ),
     LotteryTicket.new( 24, 6, 8 )

当選を決める段になって、ペイジ-リーの父親(くじ主)は数字をランダムに選ぶコードを追加した。

 class LotteryTicket
   def score( final )
     count = 0
     final.picks.each do |note|
       count +=1 if picks.include? note
     end
     count
   end
 end

score メソッドはLotteryTicket のインスタンスを、当たり番号に相当するランダムに選んだチケットと比較する。ランダムチケットはfinal引数で渡される。チケットは一致した数1つにつき1ポイントの点数がつく。score メソッドは点数のトータルを返す。

 irb> ticket = LotteryTicket.new( 2, 5, 19 )
 irb> winner = LotteryTicket.new( 4, 5, 19 )
 irb> ticket.score( winner )
   => 2

ペイジ-リーが時にどれほど聡明であるかを見ることになる。彼の父はくじの完成を彼に任せた。チケットへの需要の高まりによって、くじ主は日中の時間をすっかり取られてしまっていたのだ。若きペイジ-リーが堅苦しいスーツを着て、会社の会議で輪ゴムを親指ではじきながら、システムの最後の部品について提案している姿なんて想像できないだろう。確かに、彼が立ったとき、彼の父親は彼のために話す部分は全部やったが、ペイジ-リーはプロジェクターをつけて、 手振りの部分は全部やったのだ。

 class << LotteryDraw
   def play
     final = LotteryTicket.new_random
     winners = {}
     @@tickets.each do |buyer, ticket_list|
       ticket_list.each do |ticket|
         score = ticket.score( final )
         next if score.zero?
         winners[buyer] ||= []
         winners[buyer] << [ ticket, score ]
       end
     end
     @@tickets.clear
     winners
   end
 end

彼の父親の共同経営者たちは驚いた。これは何だ? (ペイジ-リーは、これがただのクラスメソッド定義だと知っていた——ペイジ-リーが彼らにそう 話したら、彼らはみんなすっかりまごついたことだろう。) 彼らはそこにある二重の小なり記号が理解できなかったのだ! そう、これは連接オペレータだが、クラス名のところに出てくるというのはどういうことだ?

「初心者」とペイジ-リーは思った。彼は彼らをみなとても尊敬はしていたが。彼はただの子供で、子供というのは煉瓦の歯のようにタフなのだ。

 << オペレータでオブジェクトの定義を変えることができる。ペイジ-リーが単にLotteryDrawクラスを使ったなら、play メソッドは通常のインスタンスメソッドになる。しかし彼は<<オペレータを使ったので、play メソッドはクラスに直接、クラスメソッドとして追加される。

class << objというのを見たら、obj定義に直接追加しているのだと心の中で思ってほしい。

若きオルガン教師はまた、よく調べるに値するトリッキーな構文も使っている。9行目の、当たりが見つかったところだ。

 winners[buyer] ||= []
 winners[buyer] << [ ticket, score ]

||=と言う構文は次のように書くことのショートカットだ。

 winners[buyer] = winners[buyer] || []

二重のパイプ論理和だ。winners[buyer]winners[buyer]を設定するか、あるいはwinners[buyer] がnilであれば[]を設定する。このショートカットは少し奇妙だが、頭の中にしっかり埋め込むことができれば、これで時間の節約ができる。これは変数が使われる前に間違いなく値が設定されるようにしているだけだ。

 irb> LotteryDraw.play.each do |winner, tickets|
 irb>   puts winner + "" + tickets.length + "枚当たりました!" 
 irb>   tickets.each do |ticket, score|
 irb>     puts "\t" + ticket.picks.join( ', ' ) + ": " + score
 irb>   end
 irb> end

 グラム-ヨルは2枚当たりました!
     25, 14, 33: 1
     12, 11, 29: 1
 ターカー-アゼインは1枚当たりました!
     13, 15, 29: 2
 ブラムロー-エクソンは1枚当たりました!
     2, 6, 14: 1

しかしペイジ-リーと彼の父の世間知らずの青年時代は長く続かなかった。彼の父はよくユニフォームを洗濯せずにいて、肩にコケ病ができた。この病気はゆっくりと彼 から落ち着きと方向感覚を失わせた。

彼の父は依然ビジネスを動かし続けようと無駄に努力していた。彼は町中を回り、ときどき脚をもつれさせて舗道に転びつつ、 多くの場合ゆっくりと壁をさわりながら歩き、店から馬車のステーションまで煉瓦を数えながら行き、そこで見物人にチケットを突き出すと、その人は彼を追いかけて長く湿ったビートで叩いて追い払 うのだった。後にペイジ・リーが彼をある街角で見つけたとき、彼の血は暗くはねちらかされたビートの汁とともには町の排水溝に流れ、ビートの汁が彼の静脈に入り込んで苦痛を与え、固まり、有料橋への道を争うブレーキランプの群れのようにどう猛に光った。

 

アクセサについて一言(なぜなら私はあなたを愛していてあなたの成功を願っており私の髪は逆立っていて夢は本当に実現するから)

前に、私はattr_readerリーダーメソッドについて話したが、ライターメソッドについては話していなかった。

 irb> ticket = LotteryTicket.new
 irb> ticket.picks = 3
 NoMethodError: undefined method `picks=' for #<LotteryTicket:0xb7d49110>

これは今の場合問題ない。ペイジ・リーの父はチケットが購入された後に番号を変えられたくはなかったからだ。もしリーダーライターの両方を 持つインスタンス変数 がほしいなら、attr_accessorを使えばよい。

 class LotteryTicket
   attr_accessor :picks, :purchased
 end

これは次の長いコードとまったく同じだ。

 class LotteryTicket
   def picks;           @picks;            end
   def picks=(var);     @picks = var;      end
   def purchased;       @purchased;        end
   def purchased=(var); @purchased = var;  end
 end

聖なる猫よ! このwriterメソッドをちょっと見てほしい。picks=purchased=という名前のメソッドだ。これらのメソッドはインスタンス変数への外部からの代入を横取りする。通常あなたはただattr_readerattr_accessor (あるいはattr_writer)に仕事させればよい。しかしときには、戸口に自分でガードを付けて変数を細かくチェックしたいと思うかもしれない。

 class SkatingContest
   def the_winner; @the_winner; end
   def the_winner=( name )
     unless name.respond_to? :to_str
       raise ArgumentError, "優勝者の名前は文字列でなければなりません。数学の問題や
         名前のリストみたいなものであってはなりません。" 
     end
     @the_winner = name
   end
 end

ほとんどの場合、あなたはこれを使わないだろう。しかし、このレッスンを続けていくうちに、あなたはRubyにはたくさんの逃げ口や裏通りがあって、忍び込んだりハックしたりできるのがわかるだろう。私はあなたがメタプログラミングもできるようにするつもり だ。もしドラゴンのにおいを感じたなら、それは不吉なくらいに近いということだ。

ペイジ・リーは若く進取の気性に富むエンダートロム人だった。彼はミュージシャンが指につけたコルクで閉じられる深い穴のあいた、長いぴかぴかしたトランペットを動物の骨から作った。それは3本しか売れなかったが、彼はフリーランスの悪魔のような学者として広く罵られた。彼は貧しい階層の出身で、貧しい者は悪魔的な実践によってのみ輝きを得ることができたのだ。もちろん彼らは正しく、実際彼は暗黒の魔法使いと契約を結んでいた。彼はその魔法使いと毎年アポイントメントを取り、温泉の苦痛に耐え、呪文を唱えながら沐浴した。

彼の父はジャイロスコープのように悪くなっていたが、それでも彼は父親のことが好きだった。彼は父親の仕事に心酔し、自分のわずかの稼ぎもくじに使っていた。それぞれ中空の粘土の玉に書かれた数字がロブロック(これは池やこぼれたものといった任意の流体で、たまたま幽霊の存在に耐えることができた)に昇り、胴元たちがそれを銀の紐で結び合わせ、順に読んで いくのを見ているのが彼は好きだった。

今日でも、ペイジ-リーはそのシーンをアルミホイルのシートに黒いインクの粗いストロークで描く。彼が貴重な記憶を取り戻すのを見るのは感動的だが、なぜ彼がアルミホイルに描 くのかはわからない。彼の絵はすぐ破けてしまう。ペイジ-リー自身混乱していて、このアートのすぐあとにクラムケーキでもてなしてくれる。絵がちゃんと額装された後でも 混乱している。だから彼に関する多くのことにはトラブルがあり、ばかげていて、まったく哀れだ。

病気は彼の父親の体全体に広がり、じめじめした雑草が手と顔を覆っていた。コケは彼の背骨を堅い直立姿勢に引き上げた。彼の頭の上には濃い茂みがあり、潅木を植えた山高帽をかぶっているように見えた。彼はまた、自分を新しい名前クォスで呼び、触れた人を 癒した。町を旅する彼の後には純血の緑の頬の村人たちの山が残された。多くの人は彼をモシア(Mossiah)と呼び、彼の前に跪いて泣き、その涙が彼の芽を濡らして地面に根付かせた。これ に怒った彼は脚を荒々しく動かして自由にし、こぶしを激しく空に伸ばし、稲妻のかけらの嵐をその哀れなものたちに降らせた。

ペイジ-リーは彼の父親(実際はすでに死んだものと思っていたが)の精神的オデッセイからは距離を置いていて、ただ主のいないくじが衰えていくのを見ていた。そしてペイジ-リーは ここにおいて、廃れた家族のくじを復活させるべく動き始めた。

 

少ない指でギャンブルする

町はくじに興味を失った人で溢れていた。天候もまた人々をすっかり参らせていた。ひどい雨が彼らの地下貯蔵庫を水浸しにしていた。町全体が1階上に移動せざるを得なかった。ペンにキャップをかぶせようとするとペンを駄目にすることになった。キャップはすでに水でいっぱいになっていたからだ。みんな消耗し、多くの人が溺れ死んだ。

ペイジ-リーは水面レベルよりかろうじて上にあった唯一の家具である4段ベッドの上で一日を過ごしていることに気づいた。彼は一番上のベッドで寝ていた。3段目も乾いていたので、彼は家なしのクレーターカモメに巣を作らせていた。カモメはベッド全部は必要としなかったので、ペイジ-リーは電卓と鉛筆をそこに置いていた。

最初これは彼らのどちらにとっても暗い時期であり、彼らはあえてやつれた状態にいた。ペイジ-リーはつめに執着するようになり、つめを長くきれいに保っていたが、そのほかの部分は体を覆うほどになった髪の下で ひどいことになっていた。ペイジ-リーと一緒にクレーターカモメも異常なことをするようになり、体の右側の羽をすべて引き抜いてしまった。それは何か断面図みたいに見えた。

やがて 彼らは時を楽しく過ごす方法を学んだ。ペイジ・リーはつめで壁からフルートを彫り出し、時々それを演奏した。多くの場合彼は日中に自分で作ったゆったりしたバラードを演奏し 、夜になるとそれが彼の歌に合わせて壁にはねかえりベッドのフレームを揺らした。ある4つの音符を演奏するとカモメがおかしくなるので、彼はそのセクションを繰り返し演奏し て、カモメが夢中になって急降下したり弧を描いたりするのを見ていた。ペイジ・リーはちょっとした旋律の持つ効果に対して平静を保つことができず、 まとめておくこともできずにバラバラになり、よだれを流したり馬のいななきをしたりした。

ペイジ-リーはカモメを、そのお気に入りの歌から取ってEb-F-F-Aと呼んだ。

友情とは進歩のためのとてもいい触媒になる。友達は他の誰も気づかないあなたの特質を見出す。それは彼らがあなたの人物を探索してどうやってかあなた自身あることも知らなかった銀食器 を5セット見つけ出してくるようなものだ。そしてその友達はあなたが何で台所用品なんか隠していたのか分からないかもしれないが、それでもそれは依然偉業であり、賞賛に値する のだ。

Eb-F-F-Aは銀食器は見つけなかったが、別なものを見つけた。何か別なものの山だ。ペイジ-リーは4段ベッド の上に取り残されていたから、カモメが食べ物を探した。ある日、カモメは道具小屋があったところに浮いている樽の上に降り立った。 Eb-F-F-Aは樽の上を歩き、ペイジ-リーの家の方に転がしていった。彼らがそれを開けてみると、なくしていたペイジ-リーのカモノハシのコレクションが現れた。

そう、本物のカモノハシ(duck bill)だ。(Eb-F-F-Aは鳴き声を飲み込 んで平静を保ち、 額を流れる汗の玉を吸った——アヒル(duck)は彼の仲間ではなかったが、それでも同類ではあった。) ペイジ-リーは大喜びして手をたたいた。彼は家の屋根をこれで葺くつもりでいたのだ。これで水の流れをすこしそらせるかもしれない。たぶんそれほどではないだろうが、騒ぐほどのことではない。

屋根用の糊は樽の底にあり、時間の有り余った商魂たくましい寝棚をともにする2人は、かつてガーガー泣いていた口の覆いからいかだを作ることにした。いざ田舎へと漕ぎ出すのだ! 町のまったくの混乱をかき回すのだ。たどり着いた岸がトッフルタウン交差点を通る古い未舗装道路だったというのはすごく奇妙だった。

田舎で彼らは商売をした。次のプランテーションまでは長い道のりで、屋敷には買い手があまりいなかった。(「ようこそビート屋敷へ」とか「セロファン代用物屋敷——本物のセロファンがどれほど有害か知ってます か?」とか書かれていた。)  ある家族はあまったゼリーとハムをセロファンに包んで2人の旅行者にくれた。そして彼らはそのため翌日ほとんど死にそうになった。

それから、暑い時期が来て、最初の田舎のくじが近づいたとき、ある農夫が畑から彼らに声をかけた。彼は草を食む牛のそばに立っていた。ペイジ-リーとEb-F-F-Aは彼に近づいてい きながら、ウィンドビートン・チケット・スペシャルを勧めたほうがいいだろうか、あるいは彼はリスキーロスコのオリジナル家庭風カントリーメダリオンを引き当てる方を選ぶだろうかと話し合っていた。

しかしその農夫は彼らが近づいてくるのを手を振ってとめた。「おたくの電卓とルーレットはしまってくれ。それは私のグレイズルドン向けだ」。それは牛を意味していた。エンダートロム版 の牛で、2倍肉付きが良く、2倍豊かで、ミルクを出さず、紙の皿を作る。それでも草を食べる。

「あなたのグレイズルドン(ポー コン イック)は幸運のチケットを欲しがるでしょうか?」とペイジ-リーが聞いた。

「おたくら二人を見てこいつはとても興奮してたよ」と農夫が言った。「こいつは数はわからないが、幸運は少しわかる。こいつは一度ぼけた飛行機にほとんどはねられそうになったんだが、 俺が見つけたとき、肩をすくめたんだ。それは『結果としてはOKだ』と言っているみたいだった」

「くじ(シャス オプ)は全部数字(イグ イグ)です」とペイジ-リーは言った。「彼は音符は(エルシュ)わかりますか? 私のワシは(ロシュ)音符がわかります」とペイジ-リーはクレーターカモメに口笛で合図すると、カモメは長く伸ばしたDの音で返事した。

農夫はグレイズルドンの音色認識能力に語りかけることができなかったので、ペイジ-リーは調べるようにカモメを送り(D-D-D-A-D行って-グレイ-ズルに-教えて-やれ)、その 間自分は計算機に音符を組込んだ。

 class AnimalLottoTicket

   # 有効な鳴き声のリスト。
   NOTES = [:Ab, :A, :Bb, :B, :C, :Db, :D, :Eb, :E, :F, :Gb, :G]

   # 選択された3つの鳴き声と購入日を保存する。
   attr_reader :picks, :purchased

   # 選択された3つの鳴き声から新しいチケットを生成する。3つの鳴き声はそれぞれ異なっている必要がある。
   def initialize( note1, note2, note3 )
     if [note1, note2, note3].uniq!
       raise ArgumentError, "異なる鳴き声を選んでください" 
     elsif picks.detect { |p| not NOTES.include? p }
       raise ArgumentError, "半音階の中から選んでください" 
     end
     @picks = picks
     @purchased = Time.now
   end

   # 当たり番号に対するチケットの点数を求める
   def score( final )
     count = 0
     final.picks.each do |note|
       count +=1 if picks.include? note
     end
     count
   end

   # ランダムなAnimalLottoTicketを生成するコンストラクタ
   def self.new_random
     new( NOTES[ rand( NOTES.length ) ], NOTES[ rand( NOTES.length ) ],
          NOTES[ rand( NOTES.length ) ] )
   rescue ArgumentError
     redo
   end

 end

アニマルチケットは普通のチケットとそんなに大きく変える必要はない。AnimalLottoTicket クラスは、中身は変わっているが元々のLotteryTicket クラスと同じメソッドを公開している。score メソッドなんかLotteryTicketscore メソッドとまったく同じだ。

音符のリストはクラス変数を使うかわりにAnimalLottoTicket::NOTESという定数に入れている。変数は変わるが音符は変わるべきでない。定数は同じであり続けるようにデザインされている。それでも定数を変えることは可能 なのだが、その場合うまくやらないとRubyに文句を言われることになる。

 irb> AnimalLottoTicket::NOTES = [:TOOT, :TWEET, :BLAT]
 (irb):3: warning: already initialized constant NOTES
   => [:TOOT, :TWEET, :BLAT]

カモメはグレイズルドンと一緒に戻ってきた。彼の名はマーフィといい、賭をするのはわくわくすると言って、夢見るような顔を見せ、一続きの5つか6つの音符を鳴らした。彼らは マーフィの首輪をつかんで計算機の方に引っ張っていって3つの音符を出させ、チケットがプリントされて @@tickets['マーフィ']にすべて登録されるまで、口をふさいでいた。ありがとう、抽選の時にまた!

そうして無邪気な動物たちの間でくじに対する熱狂が広まった。ペイジ-リーは彼の子供時代のくじの環境で使われていたのと同じLotteryDraw クラスを使うことでコストを節約した。ほどなく動物たちは自分の音楽や地図や映画を作るようになった。

「それでオリジナルズはどうしたんですか?」と私はペイジ-リーに聞いた。「彼らは動物を憎んでいたはずです!」

しかし彼は気難しく顔をしかめ、額に皺を寄せた。「私はオリジナルです。あなたもそうです。私たちは(エイ オ)動物を憎んでいますか?」

くじが終わってそれほどしないときに、ペイジ-リーはクレーターカモメEb-F-F-Aが肩に舞い降りて悲しく差し迫った調子でC-Eb-D C-A-Ebと鳴くのを聞いた。この絶望的な報告は、オルガンロール1本分の寒気をペイジ-リーの体に走らせた。ポットに入った土の王、 我らの愛すべき装飾庭園、モシア ・クォス、私の娘のオルガン教師になるべき男の文字通りの父親が、本当に終焉を迎えたのだろうか? どうしてそんなことが起こりえるんだ? 大いなる木陰が彼を育み、湿った横風の中を導いてくれることはもはやないというのか? あるいは彼の長く伸びた地衣類の生け垣が彼の方に伸びて息を遮ったのか?

「 気に病むことはない」。カモメの旋律が続いた。 「彼は悪化し、弱って、別荘の灯りのついた戸口に倒れた。彼の巻きひげは日が終わらないことを必要とし、叫んだ。太陽が固定し、広がり、親切にしてくれることを求めた」

家の付添人のプロー-リアンが水差しを運び続け、ペイジ-リーが到着して腐りゆく柔らかい植物のつぼみと父親であるくじ主の顔を確認するまで、クォスはよく水を与えられていた。彼の皮膚には 過剰に刺繍を施した枕のように深い穴があいていた。袖から萌え出ていた芽は乾いて丸まっていた。

ペイジ-リーは父親の目の周りの長い茎と、口の角から出ている茎を梳いた。ペイジ-リーの涙が袖を流れ落ちて父親に注がれ、それが草に覆われた紳士を若返らせ、回復させたと言いたいところだが、そう言うことができない。

むしろペイジ-リーの涙は彼の袖を伝って軋む羽目板の床に落ち、嫌らしい雑草を育み、暗い植物に力を与え、それは文字通り床を突き抜けて伸びて我らがクォスにからみつき、つかみ、引っ張り、割った。それは彼の頭蓋骨だった。

だからペイジ-リーがその後ワート-リーやワート-プロと呼ばれることはなかった。

6. ルールを作る者たち

ハンナは壁から飛び退いて、しゃがみ込んだ。

「これがあの壁だ」とドクター・チャムが言った。「オリジナルズはあの中にいる。ハンナ、監視デッキに私たちを連れて行ってもらえるかな?」

「君は私たちで彼らに立ち向かおうというのか?」とヤギが聞いた。「連中はコアラみたいに狂ってるんだぞ。しかもこのコアラはレーザーを持っているんだ!」

「しかし私たちは勝つよ」とドクター・チャムは言った。「君と私はそのことを知っている」

「ああ、しかし私はその辺が心許ないんだ」とヤギが言った。「私たちは本当に勝つのか? あるいはクレイマークレイマーのことを考えているんだろうか? ダスティン・ホフマンが勝つのか、私たちが勝つのか?」

「いや、いや、いや、いや」とハンナが浮遊して神経質そうに足を壁に引きずった。「あそこに大きな顔のある男がいるわ」

「ミスター・フェースだ」とドクターが言った。「彼は顔の原型だ」

「彼は私をわかっていない」とハンナはうめいた。ホマ ホマ アロ アロ。

彼女のうつろな泣き声はぼろぼろのネズミ穴と冷蔵庫のゲートウェーを通って響き、ビデオチェックポイントがシューッと音を立て、壁のパネルが開き、それから静かになった。3人は壊れたセキュリティを2レベル通り抜け、貨物室を見下ろす監視デッキに出た。

Klon Ooper. Corwood. Mr. Face. Vonblisser.  The Originals.

・・・クロン・ウーパー、黒幕の事業家ゾウ・・・

・・・コーウッド、余分な詰め物をした鳥・・・

・・・ミスター・フェイス・・・

・・・それにもちろん、ボンブリッサー、すごく感じのいい(しかし依然邪悪な)シカ・・・

「オリジナルズの最後の生き残りだ」とドクター・チャムが言った。「もう大丈夫か、ハンナ?」 彼女は聞いておらず、彼女の目は伝説の生き物たちに注がれていた。

「彼らを見て」とヤギが言った。「連中がルールブックを書いたんだ、ドクター。私たちはすべてをこの連中に負っているんだ」

「神は?」ドクターが言った。

「私には本当のところわからない」とヤギが言った。「ハンナがおそらくそのことについては一番よく知っているんじゃないか」

ハンナは何も言わなかった。彼女は他の幽霊を1人知っているだけで、それは彼女の死後の橋渡し役のジェイミー・ハフトだった。その人は答えを何も持っていないようで、質問は返信用の切手を貼った封筒を同封して郵送するように求めていた。ハンナはその私書箱にはまだ手紙を送ったことがなかった。

「山の中では起きてなきゃいけない」とヤギが言った。「闇に気をつけることだ」

「ハンナを見つけた場所でここと似たデッキを見た」とドクター・チャムが言った。「君の居住区に近いところだ。君はそこの探索に時間を使うべきだ。とても静かな場所だ。地球と7つの海が見える」

「7つの海?」 そこはロケットの近くなのかしらとヤギは思った。彼はラインダンスについて読み、ステージを大きなロータリー耕耘機みたいに気取って歩く脚の線を見たことがあった。

ハンナが元気付いた。

Hannah panicks. Maple donuts are within reach.

「見て!」

みんなが見ると・・・間違いない! ミスター・フェイスは長いメープルバーを持っていた・・・彼の手の中に!

ヨダレ ヨダレ ヨダレ・・・

「シーッ!
こっそりとドーナツを手に入れなきゃならないんだ!」

They couldn't hear them, but they saw their slides.

コントロールブースからは、オリジナルズの会話を聞くことはできなかった・・・

・・・しかしスライドが見えた!

彼らは動物の首都、ウィグズルを目指していたのだ!

そしてオリジナルズがスライドプロジェクターを切り、とても細いロケットに乗り込んで、貨物室の屋根の割れ目を通って見事に発射したとき、3人の誰も口を開かなかった。

「ああ、なんてことだ」とヤギが言った。

「何?」とハンナ。

「君は死ぬことになる」とヤギは言った。

ドクター・チャムは彼らの前にある、ハンドルが並んだ長いパネルと緑色のスクリーンのある制御盤を見ていた。

「私はもう死んでるわ。幽霊なのよ」

ヤギはドクターに目を向けた。彼はコントロールパネルの下を探っていた。「OK、君のおじさんが話してくれないなら、私がはっきりさせよう。あの連中が爆弾を作る可能性が高い。私がどんなに気を揉んでいるかわかるかい? 私の膝がガタガタしているのがわかるだろう?」

「ええ」

「これがどれほど現実かということだ。私はあのいまいましい本の中身を、あの連中が幽霊の世界を吹き飛ばせる爆弾を作っているということ以外何も覚えていない。幽霊の世界がなくなれば、ディガー・ドシュ は1秒を取り戻せる。それが彼らの練り上げた取引なのだ。むかつく話だが、君はこのことを知っている必要がある」

「でも私は死んでるのよ」

「でも、私たちは話してるよね? 君は話せるのに、死んでるというの?」 ヤギは頭を振った。「勝つのが私たちなのか、それともダスティン・ホフマンなのか、覚えていたなら」

ハンナが叫んだ。「どうして私がまた死ななきゃならないの?」彼女は泣き叫び、彼女の脚は溶け、床に沈んでいった。モオ モオオオオ マウ マウウウウ。

ドクター・チャムが立派なハンドルを力をこめてぐいっと引くと、鍵が外れてブレッドボックスみたいに開いた。彼は中に手を入れて、奥の方にしっかりとボルトで留められたキーボードを見つけた。

「これだ」と彼は言い、irbを起動した。それは彼が隠れてタイプしている左側のディスプレイに現れた。彼はRubyのバージョンをチェックした。

 irb> RUBY_VERSION
   => "1.8.2"

Rubyはアップデートされている。他にできることは何か?  constantsclass_variablesを調べるのは意味がない。Elevator クラスでそれがうまく行ったのは、誰かがクラスがロードされた状態でirb を立ち上げっぱなしにしていたためだ。

今回はirbをロードしたばかりなので、特別なクラスはまだ何も使えない。彼は何かのクラスを見つける必要があった。彼は`rbconfig`ファイルをロードし、Rubyの設定がどうなっているか 調べ始めた。

 irb> require 'rbconfig'
   => true
 irb> Config::CONFIG
   => {"abs_srcdir"=>"$(ac_abs_srcdir)", "sitedir"=>"bay://Ruby/lib/site_ruby", ... }

全部見るにはあまりに多くの情報がある。Config::CONFIG定数はハッシュになっていて、Rubyをセットアップするのに使われる環境設定がすべて入っている。オペレーティングシステムの名前はConfig::CONFIG['host_os']で知ることができる。Rubyライブラリが格納されているディレクトリはConfig::CONFIG['rubylibdir']でわかる。RubyプログラムはヘルパーファイルをConfig::CONFIG['datadir']に格納することができる。

ドクター・チャムが本当に必要としていたのは、Rubyのコアライブラリでないライブラリすべてのリストだ。オリジナルズか、あるいはこのコンソールを担当していた誰かがインストールしたライブラリだ。その情報を得るため、彼はグローバル変数の情報をチェックした。

 irb> $" 
   => ["irb.rb", "e2mmap.rb", "irb/init.rb", ... "rbconfig.rb"]
 irb> $:
   => ["bay://Ruby/lib/site_ruby/1.9", "bay://Ruby/lib/site_ruby/1.9/i686-unknown",
       "bay://Ruby/lib/site_ruby", "bay://Ruby/lib/1.9", 
       "bay://Ruby/lib/1.9/i686-unknown", "."]

ああ、いいぞ。ドクター・チャムは髭をなでながら、irb セッションを見ていた。グローバル変数$"requireでロードされたすべてのライブラリの配列を持っている。これらのライブラリのほとんどはirbによってロードされたものだ。'rbconfig.rb'はさっき彼がロードしたものだ。

  グローバル変数$:$LOAD_PATHでもアクセス することができ、requireでファイルをロードしようとするときにRubyがチェックするすべてのディレクトリのリストが入っている。ドクター・チャムがrequire 'rbconfig'を実行したとき、Rubyはこのディレクトリを順にチェックしたのだ。

 bay://Ruby/lib/site_ruby/1.9/rbconfig.rb
 bay://Ruby/lib/site_ruby/1.9/i686-unknown/rbconfig.rb (*)
 bay://Ruby/lib/site_ruby/rbconfig.rb
 bay://Ruby/lib/1.9/rbconfig.rb
 bay://Ruby/lib/1.9/i686-unknown/rbconfig.rb
 ./rbconfig.rb

2番目のパスはRubyがrbconfig.rbファイルを見つけたところだ。ドクター・チャムは最初の5つのパスが絶対パスであるのを見て取った。それらはbayというドライブ上のディレクトリへのパスになっている。絶対パスはシステムによって異なる。Windowsでは絶対パスはドライブレターで始まる。Linuxでは絶対パスはスラッシュで始まる。

ディレクトリ"."相対パスであることを示している。 単独のピリオドは現在の作業ディレクトリを表す。ドクター・チャムがirbを開始したディレクトリだ。だからRubyはすべての標準的な場所を探した後、カレントディレクトリをチェックするのだ。

ヤギはドクター・チャムの肩越しにのぞき込んで、モニタや光沢のあるボタンの上に唾液があふれ出ないように唇をなめながら、これらのインストラクションを(「違う、それじゃない」とか、「そう、それだ」とか、「OK、君の選択だ」とか言いながら)見ていたが、しかし今ではすっかり入り込んでこうやったらどうかと提案しはじめた。「require 'setup'を試そう。いや、3 * 5だ。基本的な算術が機能しているか確認するためだ」

「もちろん算術は機能するさ」とドクター・チャムは言った。「構わないでくれ。私は何か有用なクラスを探しているんだ」

「これは基本的なサニティテストさ」とヤギが言った。「ちょっとやってみてよ。 3 * 5で何が出てくるか」

ドクター・チャムは降参して言う通りにした。

 irb> 3 * 5
   => 15

「OK、素晴らしい! 我々は前進している!」とヤギは言って毛むくじゃらの顔に笑みを浮かべた。

ドクター・チャムはヤギの頭を叩きながら「よくやったね。先に進もう」と言った。

 irb> Dir.chdir( "bay://Ruby/lib/site_ruby/1.9/" )
   => 0
 irb> Dir["./*.{rb}"]
   => ['endertromb.rb', 'mindreader.rb', 'wishmaker.rb']

ドクター・チャムはchdirで作業ディレクトリを$LOAD_PATHのリストの最初にあるパスに変えた。最初のパスのsite_ruby というのはカスタムクラスを置く場所として一般に使われている。

そこにはこの章の始めの方で私の娘のオルガン教師が私のために書いてくれた伝説的な3つのクラスがあった。そしてドクター・チャムはこの章を読んでいるので、システムのこの3つ部分に即座に気付いた。

Endertromb クラスはこの惑星のパワーの謎を握っている。MindReader クラスは居住者の心をスキャンして心の中身を読み取る。そして最後に、重要なWishMakerクラスがあり、これはエンダートロムの中心への道を見出せた10文字の望みをかなえる力を持つ。

4 * 56 + 9はどう?」とヤギが聞いた。「複合式ができるかまだわからない」

MindReaderを見つけたよ」とドクター・チャムが言った。「そしてWishMaker もある。この惑星は心を読める。そしてこの惑星は望みをかなえることができる。両方を同時にできるかどうか見てみることにしよう」

7. 夢を生きる者たち

オリジナルズの船が消えてからずっと、ドクター・チャムは熱心に監視デッキのコントロールパネルに組込まれたコンピュータに取り組んでいた。ハンナは床の中に消えていき(あるいはあの地面の小さなスパークは彼女の科学では説明の付かない存在の一片かもしれない!)、ヤギはドクター・チャムがRubyモジュールをハックするのを穏やかに見ていた。

 require 'endertromb'
 module MindScanner
   def scan_for_a_wish
     wish = self.read.detect do |thought|
       thought.index( 'wish: ' ) == 0
     end
     wish.gsub( 'wish: ', '' )
   end
 end

「どうするつもりなんだ?」とヤギが聞いた。「私なら3行でこの問題を解けたように見える」

「このモジュールは新しいMindScannerテクノロジーだ」とドクターは言った。「このスキャナーはwish セミコロン スペースで始まる望みだけを拾い上げる。そうすることでこの惑星が人々の頭にうかぶ10字未満の語でいっぱいにならないようにするんだ」

「どうしてただのクラスを使わない?」とヤギが聞いた。

「モジュールはクラスよりも単純だ。これは基本的にメソッドの貯蔵施設というだけのものだ。メソッドのグループをまとめておくものだ。メソッドから新しいオブジェクトを作ることはできない」

「しかし実際使うためにはMindScanner オブジェクトがいるんじゃないか?」とびっくりしてヤギが言った。

「これをMindReaderにミックスするんだ」とドクター・チャムは言い、その通りにした。

 require 'mindreader'
 class MindReader
   include MindScanner
 end

「これでMindScanner モジュールはMindReaderにミックスインされた」とドクター・チャムが言った。「scan_for_a_wish メソッドがどのMindReaderオブジェクトからでも呼べるようになった」

「それがミックスインか」とヤギが言った。「MindScannerミックスイン」

「そう、includeでクラスに取り込まれるモジュールは、そのクラスのミックスインだ。scan_for_a_wish に戻って見てみれば、それがself.readメソッドを呼んでいるのがわかるだろう。MindScanner がミックスインされるクラスがread を持つか確認するだけでいい。持っていないとエラーが投げられることになる」

「ミックスインがまだないメソッドを必要とするというのは奇妙だ。自分でやるべきように思える」

ドクター・チャムはキーボードから目を上げてヤギを見た。「これは君のビデオコレクションみたいなものだ。君のビデオカセットは、そのビデオカセットを使う機械に 入れないと使えない。それらは互いに依存しているのだ。ミックスインは基本的な要求を持っているが、クラスがひとたびその要求を満たせたなら、すべてのそのほかの機能を手に入れることができるんだ」

「そいつはクールだ」とヤギが言った。

「君はあの本を30回読んでそれがわからなかったのか?」とドクター・チャムが聞いた。

「君はいい教師だよ」とヤギが言った。「私は君のことが好きになるとは本当に思ってなかった」

「それは理解できるよ」とドクター・チャムが言った。「マンガで見ているよりはこれはずっとリアルなことなんだ」

 require 'wishmaker'
 reader = MindReader.new
 wisher = WishMaker.new
 loop do
   wish = reader.scan_for_a_wish
   if wish
     wisher.grant( wish )
   end
 end

irbは画面でループして待ち、Ctrl-Cを打つまで続ける。しかしドクター・チャムは回し続けておいた。終わりなく回り、精神の波から適正な望みを探すのだ。

ドクター・チャムは自分の望みの準備をした。最初stallion(雄馬)いうのを思いついた。その背にまたがってセドナの谷に行くために。しかしその考えは引っ込めた。その望みは適正な形をしていない。stallion はオリジナルズを追いかけるのには役立たずだ。それで再び目を閉じて、心の中で考えた。wish: whale

 

ピープルマッドへの最後のクジラ

城の入り口でハンナが手でバラのつぼみを叩いていたところへ、がっちりした体の無愛想なクジラが現れた。彼女は拳でクジラを叩いたが、それは変わらず完璧で、感じよく、エンダートロムの青い空にくっきりとした姿を見せていた。

「退屈よ」と彼女はクジラに言った。ボオ ボオ オオオオーー。

「OK」とクジラが深くやさしい声で言った。言葉は彼の巨大な舌を滑り下りながら角が取れ、磨かれすり切れた泡となって彼の口の端から出てきた。

「私はいつだって死ななきゃいけないのよ」と子供の幽霊が言った。「みんないつも私を殺すの」

クジラは地面から無駄に離れた短いひれをはためかせた。それで今度は尻尾で押して、自分の体を彼女の方に近づけるよう、草地の上を進んだ。

「みんな殺すって、誰を殺すの?」少女が言った。「私。彼らは毎回私を殺す」

クジラは少女から3メートルまで近づき、たくさんの死んだ兵士を表す大きな戦争記念碑のようにそびえ立った。クジラはしっぽを休め、ここまで登ってくるので疲れ果て、まぶたを閉じてやさしく息をする粘土の山のようになった。彼の影はほとんど見えないハンナの上に落ちた。

しかし細く、確固とした別な影が加わった。彼女のすぐ後ろから、彼女の肩に手が伸び、手の中の暖かい幽霊は彼女の袖に触れた。

「どうやってここに下りてきたの?」と少女が言った。

「ドクター・チャムは彼女の側に座り、ヤギはぐるっと歩いて前に立った。

「聞いて」とドクター・チャムが言った。「私たちはあのろくでなし集団を追いかけなきゃいけない、ハンナ、そして彼らを捕まえるために、君の助けが必要なんだ」

「怖いわ」とハンナが叫んだ。

「君は恐れていない」とヤギが言った。「さあ、君は怖い小さな幽霊なんだ」

「そうね」と彼女は言った。「私少し退屈したわ」

ドクター・チャムは跪き、彼の髭だらけの顔を彼女から数インチのところまで近づけた。「君が私たちと来てくれるなら、私たちの知っていることを信じられるなら、あの汚い連中を捕まえることができる。さあ、君は自分の運命がパン屋になることだと言ったね。私は反対しない。君にはパン屋になれる地球における——そしてこれに関してはエンダートロムにおける——あらゆる権利がある。君がパン屋にならないなら、それは大きな悲劇だ。君がやらないとしたら、 一体誰があのたくさんのドーナツの面倒見るというんだ?

彼女は肩をすくめた。「それは私がずっと言っていたことよ」

「その通りだね」とドクターは言った。「君は始めからそう言っていた」。彼は空を見上げた。オリジナルズの宇宙船が強引に突き抜けていったにもかかわらず、そこには穏やかな風が吹いていた。「君の運命がパン屋になることなら、私のは今まさに吹き出そうとしている破壊を止めるということだ。良く聞いて——私がこれを言うとき、私の声にどれほど確信があり確固としているか——私は君の人生を終わらせた。私は君の幽霊としての人生に責任がある。しかし私は取り戻してみせる。ドーナツ以上のものが必要になるだろうが、君は本当の子供時代を迎えることになる。約束するよ」

On the wished whale... away...

「このクジラがここで私たちを待っていてくれていると思った」

「メープルドーナツを全部食べちゃだめ」

そしてドクターと幽霊の少女はクジラの背によじ登った・・・

「メープルドーナツの生涯と新しいフィルムストリップが欲しい」

ヤギが望みを10字に切りつめるのには少し時間がかかったが、彼は同じジェットストリームに乗ってドクター・チャムと幽霊の姪のハンナの後を追った。オリジナルズと呼ばれる極悪な動物コンボパックに向けて。あのロケットに向けて。

彼らに遅れる1秒ごとに、ディガー・ドシュは棍棒を振るい、大いに楽しんでいるのだ。

 

ページをめくる。