6.

ダウンタウン

[o]

Lost in Wixl

「そう、私はこのテクニカルマニュアルに今出てることになってるんだけど、ピックアップを探していたら、変な動物の町で道に迷ってしまったんだ・・・」

This heist goes all the way up?

「ああ、おたくの町は変だと思うよ。そこら中動物だらけだ!」
「君には自分の意見を持つ権利があるとも!」

「うがー!!  ばかげている!! 今じゃ電話交換手まで私のトラックを盗むのを助けてるんだ!!」
「あの泥棒はトップに上り詰めたのに違いない!」

「キツネの大統領のマルコス・レジナルドが一枚噛んでると思ってるの?」
「このゴタゴタには彼の安っぽい手口のにおいがする。そうは思わない?」

オリジナルズの壮大な計画に巻き込まれていることも知らず、背の高いキツネと、ずっと背の低いキツネは、非常事態の地であるウィグズルの街へと迷い込んだ。できるなら私は彼らにそのことを知らせ たい。海岸にある孵化場へとさらっていき、彼らのとがった耳は押さえて魚の卵の山の中に隠し、豪華な隠れ家にかくまいたい。そして私は彼らの上に立って微動だにしない影を投げかけ、毅然とライフルを構える。

しかし私にはできない。打ち明けなければならないが、私は自分の面倒を見なければならないのだ。上の階の電球を交換しなきゃならない。無料のハロゲン電球がちょうど郵便で届いたところだ。誰かが私にそれを使わせようとしているらしい。だから私はその電球をねじ込む。そして 私はそこにただ立って、微動だにしない影を投げかけ、毅然とライフルを構える。

その影がきれいでくっきりしているなら、私はそれをそのまま保とう。

 

1. 私が車を探しているなら

Sitting for a moment.

「座れて楽になったよ。まったくひどいことになった」

「君にそんな目で見られるのは嫌だな」
「君は同情してくれとは言ってないし、僕は同情しないよ」

「私の鬱屈した感情を助長しようというの? 私の気楽な性格を押しつぶ してしまおうと?」
「僕の無力化する無関心と闘う備えが君にあるならね!」

私はこの2人が外にいるのを見るのが好きだ。彼らはスタジオの中ではすごく退屈していた。それで彼らは奇妙なスローガンなんかをでっち上げはじめた。とあるフレーズを繰り返し 、それに執着した。そんな不自然なキツネのナンセンスは我慢できない。

これだけは言っておこう。私は本当にものごとを大学みたいにやろうと努めている。大学には行ったことがないので、自分の書く文章が学問の世界が要求する厳格な基準に合っている かわからないが、大学には友達がたくさんいて、中には研究で世界をまわっている人もいるので、彼らのハイカルチャーのブレンドに私の調子を合わせるように努めよう。

ときどき私は学のある友達を越える仕事をした自分に拍手を送る——人気のない廊下でだけだ。人前で頭突きしたりしない——私は実際 、学派がまだ彼らの本の中にしかなく変り続けているうちから受け入れてきた。

私はプリイベンチュアリストだ。私がそれに関わるようになってずいぶん長くなるし、そうしてきたことを良かったと思っている。あなた方の中にはすでにこの本にマルクス主義の記号を探し始めている人もいる ことだろう。残念ながらそのような解釈は切り捨てざるを得ない。しかしあなたの引き出したニヒリスト的結論はどんなものであれ、研究する価値があるだろう。

何にしても、レトリックを使うのはやめることにしよう。私がプリイベンチュアリズムに触れたのは、それが我々が我慢してきたポストモダニズムに対する新鮮でやさしい代替であるということを別にすると、この 超カルトがウィグズルの住人に無料の落とし物サービスを提供しているからだ。

 require 'open-uri'
 open( "http://preeventualist.org/lost" ) do |lost|
   puts lost.read
 end

私はキツネたちにこのサービスのことを知らせる手段がない。彼らのトラックはすぐにこのリストに載ることだろうと思う。依然、ここには善意があるのだ。

あなたがインターネットに接続されているなら、上のRubyコードがそのWebページをインターネットからダウンロードして画面に表示するはずだ†。メッセージは以下のような内容だ:
                 †このサービスは現在は機能していない。

                         プリイベンチュアリストの遺失物記録簿
                         (啓発された人のための無料のサービス)
                                        ---
                      毎日更新されます。定期的にチェックしてください!
                                        ---
                                 このサービスの一部は
                         アシュレー・レイモンド・ユース・スタディ・クランに
                                委託され援助を受けています
                                        ...
                                 すべての標章と権利は
                     ポリウェイフ明け渡し執行官、ペリー・W・L・フォン・フローリングの
                       卓越した著述のもとに登録されています。彼はまた
                     ベガーズ・コミュニティ・カップに7回連続で優勝しています。
                                        ...

  この記録簿について
  ==============
  はじめての方はこれをお読みください。以下にサービスについての簡単な説明があります。最初に、我々の
  愛すべき執行官から重要なお知らせがあります。(子どもたちはみんな彼をアンクル・フォン・ガファンクル
  と呼んでいます。笑)

  重要なお知らせ
  ===========
  / 2005年4月15日 /
  大ニュースです。ウィグズルとオーディッシュ地域の8チャンネルに私たちは出ました。コーリーが見ていま
  す。私が出て、それからジェリー・マザーズも出ました。見てなかったらコーリーにメールしてください。
  彼が一番良く説明してくれるでしょう。私に言えるのは、これが私の手ぶりじゃないということです!! (チ
  ャンネル8を見ている人たちのためのジョークです。) ハリーとチャンネル8ニュースチームの皆さんに感謝!!
                                                  - ペリー

  / 2005年4月7日 / 
  私たちは本部でカーペットを調べましたが、ケイトリンのクリップボードを見張っていたなら、彼女がそれ
  を投稿するにはあまりに控えめな女性だとわかるでしょう。それは彼女にとってとても重要なことです。彼
  女は夫の受け口を撮ったとても高価なパノラマX線写真を持っていて、受け口が もっと目立っていた頃に
  旦那さんがロボコップのコスチュームを着て撮った大切な写真にクリップで留めていました。彼女は(私に)
  「彼らがそれを見れば私の言ったことの意味がわかるわ」と言いました。私にはそれが何を意味するのかわ
  かりません。 :(

  私がチェックしたのは: * フロントデスク * ホール * 待合室 * トイレ * キャンディー入れ * 大型テレビ
  のあたり * ランチカウンター * 見習いの部屋 * 軽業師の古い部屋(桜の木の絵のあるやつ) * サーバルー
  ム * 階段。部屋をもっと見つけたらこのリストを アップデートします。
                                                  - 愛を込めて、ペリー

  / 2005年2月25日 /
  サーバが3時に落ちました。私は君たちに腹を立てています。軽業師は下の階に直るまでいることでしょう  :O
  -- 追記:  直った。復帰したぞ!!
                                                  - ペリー

  / 2005年2月23日 /
  今日はいろいろ騒ぎがありました。スタンリー兄弟サーカスは12頭のラマとトレーラーとたくさんのマスタ
  ーキーと5つのテントをなくしました。彼らはまだなくなったものを探しています。冷静に。私はみんなの助
  けが必要です。このエンターテナーたちは何も持っていません。文字通りに。今日私は男の1人に紫色
  のステッカーをやりました(これは私がやさしいそぶりとしてするのを好んでいることです)。そして彼は実
  際その上で眠り、ピザソースの材料をその上で育てています。彼らはどん底にいるのです。

  だから寄付をお願いします。私たちはpaypalも何もありません。だから寄付したいと思ったら、何でもいい
  から見つけたものを送ってください(子供用自転車とか、腐りやすいものの缶詰ひと月分とか)。そしてサー
  カスの人たちの名前を上に書いておいてください。
                                                  - ペリー

  / 2004年11月15日 /
  プリイベンチュアリストの日の売り出しです。今日何かなくしたら、誰か何かを見つけた人の家から(40ドル
  以下の価値の)景品を1つ持ってくることができます。私たちはこれをすごく楽しんでいます!! 私は去年これ
  でローイングマシーンを手に入れました。すごく気に入っています!!
                                                  - ペリー

ユース・スタディ・クランはこのサービスの運営をとてもよくやっていると思う。これはちょっといんちきで陳腐だが、動物たちが所有権を本能的な仕方で主張しあうのを止め られるのであれば、私は敬意を払う。

しかしプリイベンチュアリストは若者のグループなのだろうか? そんなことがありうるだろうか? プリイベンチュアリストになる前に、少なくとも本物の冷笑主義の洗礼を受ける必要がある。そしてまず学校には通えない。だから私には分からない。

プリイベンチュアリストの遺失物記録簿の解説に戻ろう。

 L&Fサーバの使い方
 ===============
 L&Fは無料のサービスです。ものをなくしたり見つけたりするのは、プリイベンチュアリストのライフスタ
 イルを形作る不可欠なものです。あなたの信条に合うといいのですが。

 私たちはHTMLは使いません。作業を簡単にするためです。私たちのスタッフはすでに1日15時間働いています。
 (ターク、ありがとう!! ホレス、ありがとう!!)

 あなたは私たちのサービスでなくしたものを探すことができます。また、なくした(あるいは見つけた)ものを
 記録簿に追加することができます。これはしかるべきアドレスをブラウザに入力することで行います。

 検索
 ====
 なくしたものを検索するには、以下のアドレスを使います:

   http://preeventualist.org/lost/search?q={検索語}

 {検索語}を検索語で置き換えてください。たとえば"cup"を探すには以下のようにします:

   http://preeventualist.org/lost/search?q=cup

 そうすると、なくしたり拾われたりしたcupの一覧が表示されます。

 なくしたcupだけ探したい場合や、拾われたcupだけ探したいという場合には、`searchlost'や`searchfound'
 のページを見てください:

   http://preeventualist.org/lost/searchlost?q=cup

私はゲームをしているわけではない。私はトラックがどこにあるのか知っている。本当に、あなたのことをじらしているわけではない。すぐに教えてあげる。ただキツネたちを見てと言っているだけだ。

 Hummmmm.

 

 

「この公園はシマウマのにおいがする」

彼らはお手上げだ。しかしここにすばらしいツールがある。この混乱から脱出するための鍵になるかもしれない。何か手がかりがないか探ってみたい。

 require 'open-uri'

 # 語`truck'を含む落し物をすべて検索する。
 open( "http://preeventualist.org/lost/searchfound?q=truck" ) do |truck|
   puts truck.read
 end

このリストに背の高いキツネのトラックの情報はないようだ。それはかまわない。どうせキツネたちはぼうっとしているので、私たちには少し時間がある。

あなたはインターネットからWebページを取得する簡単なテクニックをすでに学んでいる。OpenURI ライブラリを使うやつだ。これは私の好きなルビイストの1人である田中哲が書いたものだ。彼はインターネットから読むのを自分のコンピュータのファイルを読むのと同じ くらいに簡単にしてくれた

前の章で、あなたの極悪非道なアイデアをテキストファイルとして保存した。そのファイルはRubyでopenを使って読むことができる。

 require 'open-uri'

 # 自分のコンピュータのフォルダからアイデアのファイルを開く
 open( "フォルダ/アイデア-教会の椅子にレタスを隠す.txt" ) do |idea|
   puts idea.read
 end

ファイルは入出力オブジェクトだ。あなたはファイルの読み書きができる。Rubyでは、すべてのIO(input-output)オブジェクトはreadメソッドとwriteメソッドを持っている。openメソッドはIOオブジェクトを滑り台でブロックの中に落とし、それを使えるようにする。IOは外の世界へのチケットだ。刑務所の鉄格子から差し込む日の光だ。(もっともあなたはOpenURIでWebページに書き込むことはできない。Webサーバにコピーするためのツールを見つける必要がある。たとえばFTPプログラムのような。)

教会の椅子にレタスを隠すことに関するあなたの極悪なアイデアを読みたい人がいて、あなたがそれをWebページとしてポストしていたと仮定すると、

 require 'open-uri'

 # Webサイトで読めるようになっているアイデアファイルを開く。
 open( "http://your.com/idea-about-hiding-lettuce-in-the-church-chairs.txt" ) do |idea|
   puts idea.read
 end

OpenURIライブラリはまた、FTPアドレスも解釈できる。これはあなたがファイルを保存できる場所の選択肢を広げてくれる。あなたのコンピュータの中でも、インターネット上のどこかでもいい。

 

ファイルを1行1行読む

あなたがOpenURIを使い、openメソッドとreadメソッドでWebから情報を得るとき、ページ は1つのStringとして取得される。何かを探している場合や、ページが大きくメモリを節約したい という場合には、ページを1度に1行ずつ読んでいくこともできる。

 require 'open-uri'
 open( "http://preeventualist.org/lost/searchfound?q=truck" ) do |truck|
   truck.each_line do |line|
     puts line if line['pickup']
   end
 end

上のコードはpreeventualistのサイトで見つかったトラック(truck)のリストを取得し、語‘pickup’を含んでいる行だけを表示する。そのようにして記述を削 って、肝心な行だけを対象として探すことができる。

上の例はインデックスの角カッコを文字列に対して使い、角カッコの中の語を文字列の中に探す。角カッコの中身は文字列'pickup'なので、文字列lineの中で語“pickup”を探すことになる。

On being funny.

「公園にいると少なくとも可笑しくしなきゃいけないないというプレッシャーは感じなくて済むね」

「我々は可笑しいということになっていたの?」
「ああ、しかも僕は最初はかなりうまくやっていたんだ・・・」

「でも今はこの新しい役がすごく気に入ってるよ——この本の破壊者だ!」

Webページがreadでロードされると、ページ全体がメモリに読み込まれる。通常 それは数千バイトにしかならない。しかしページが大きい(数メガバイトある)場合には 、たぶんeach_lineを使い、1度に1行ずつ読んでメモリを使いすぎるのを避けたいと思うだろう。

 

子ブロックへの委譲

Rubyでは、しばしばイテレータを次のような仕方で使う。イテレータは、配列やハッシュといったコレクションのそれぞれの要素を順にたどるときに使われる。IOの対象を行のコレクションと見なしてみよう。イテレータはこの行のコレクションを這い進むことができる。

 class IO
   # each_lineメソッドの定義。引数リストを持たないことに注意。ブロックは引数として
   # 書いてもらう必要がない。
   def each_line
     until eof?        # ファイルの終わりまで・・・
       yield readline  # 行をブロックに渡す
     end
   end
 end

yield キーワードはブロックを使う一番簡単な方法だ。一語で済む。カーテンに引き紐があり、スーツケースにハンドルがあるのと同じようなものだ。メソッドの中で点滅するyield ボタンを押すと、そのメソッドにくっついているブロックが実行される。ブロック内のコードが終了するまでボタンが強い赤色に輝く。それから点滅状態に戻る。やりたければ ボタンをまた押すことができる。

 def yield_thrice
   yield
   yield
   yield
 end

yield ボタンを3回素早く叩き、ブロックは3回その人生を生きる。

 irb> a = ['最初に生まれる。', 'それから明滅するイメージの人生。', 'そして最後に終わりを迎える。']
 irb> yield_thrice { puts a.shift }
 # 以下のようにプリントされる:
 #   最初に生まれる。
 #   それから明滅するイメージの人生。
 #   そして最後に終わりを迎える。

shift メソッドは配列の最初の要素を引っ張り出す。shift の床屋は髪を刈ってそれを手渡す。それから頭皮。それをずっと続けて、哀れな男が何もなくなるまで削っていく。

メソッドにくっついたブロックを見たわけだが、Rubyのメソッドはどれでも、後ろにブロックを付けることができる。

 # メソッドにブロックをくっつける簡潔なスタイル。
 # ここではブロックは中括弧で囲まれている。
 open( "idea.txt" ) { |f| f.read }

 # メソッドにブロックをくっつける冗長なスタイル。
 # ここではブロックはdoとendで囲まれている。
 open( "idea.txt" ) do |f|
   f.read
 end

yieldに引数を渡すと、その引数はブロックにも渡される。ブロックはメソッドのオートバイに 取り付けられた小さなサイドカーに乗っている。砂漠を疾走する彼らに吹き付ける風の中、メソッドは引数リストを大声でブロックに向かって叫ぶ。ブロックは自分のヘルメットを叩いて、「わかったよ、ちゃんと頭に入った」と伝える。

 # メソッドは2つのファイルを開き、結果のIOオブジェクトを滑り台でくっついたブロックの中に落とす。 
 def double_open filename1, filename2
   open( filename1 ) do |f1|
     open( filename2 ) do |f2|
       yield f1, f2
     end
   end
 end

 # それぞれのファイルの中身を並べてプリントする。
 double_open( "idea1.txt", "idea2.txt" ) do |f1, f2|
   puts f1.readline + " | " + f2.readline
 end

あなたはyield キーワードが道路標識と何の関係があるのかと不思議に思うかもしれない。それはいい質問だ。そしてそれにはいい答えがある。あなたがメソッドを実行するとき、あなたはそのメソッドに プログラムのコントロールを渡している。コントロールして自分の仕事を為し、そして答えを持って戻ってくるようにと言っているのだ。

yieldでは、メソッドは交差点で止まり、コントロールをあなたに、あなたのブロックに返す。メソッドは仕事を再開する前にあなたに仕事をさせてくれる。だからeach_line メソッドがファイルから行を実際に読み込む仕事をする間、each_line メソッドにくっついているブロックはその行を渡され、サイドカーの中でその行に対してせっせと作業するチャンスが与えられる。

 

金張りの箱の中のプリイベンチュアリズム

OpenURIや、yield を使って自分のイテレータを書く方法について、あなたはずいぶんと学んだ。遺失物サービスを使う方法も分かっている。本当に、あなたはウィグズルのガラクタの引き出しを私なしで探せるようになっている。

このサービス全体を1つのクラスの中に包み込んでしまおう。

 require 'open-uri'
 module PreEventualist
   def self.open page, query
     qs = 
       query.map do |k, v|
         URI.escape "#{ k }=#{ v }" 
       end.join "&" 
     URI.parse( "http://preeventualist.org/lost/" + page + "?" + qs ).open do |lost|
       lost.read.split( "--\n" )
     end
   end
   def self.search word
     open "search", "q" => word
   end
   def self.searchlost word
     open "searchlost", "q" => word
   end
   def self.searchfound word
     open "searchfound", "q" => word
   end
   def self.addfound your_name, item_lost, found_at, description
     open "addfound", "name" => your_name, "item" => item_lost, 
                      "at" => found_at, "desc" => description
   end
   def self.addlost your_name, item_found, last_seen, description
     open "addlost", "name" => your_name, "item" => item_found,
                     "seen" => last_seen, "desc" => description
   end
 end

コードというのはある時点で何かきちっとした形に整えてやる必要がある。上のモジュールをpreeventualist.rbという名前で保存しよう。

このモジュールはプリイベンチュアリストのサービスを使うためのとてもシンプルなライブラリだ。これはまさにライブラリの書かれる仕方だ。モジュールかクラスを手早く作り、ファイルに収め、それが気に入って世界の人 たちにもその恩恵を分け与えたいと思うなら、それをWebにのっける。

私が前にOpenURIを使ったみたいに、あなたのモジュールは使うことができる。

 irb> require 'preeventualist'
 irb> puts PreEventualist.search( 'truck' )
 irb> puts PreEventualist.addfound( 'ホワイ', 'Rubyのスキル', 'ウィグズル公園',
        "Rubyのスキルが身に付けられます!\npoignantguide.netへお越しください!" )

 

2. 一方、ヤマアラシは給油に立ち寄っている

The porcupine pays for gas.  Kites?

「9番ポンプ」

 

「凧は売ってる?」

 

3. スポンサー付きのドラゴン退治

The slayer hops in.

「ぼくはドラゴンを退治した!」
「ジェットスキーで戻ってくるのを想像してみてよ・・・」

「ドラゴンの顔をウィザブラムで吹き飛ばした」

ドッカーン

「シーッ! 友達が休んでるんだ!」

「何が幸運かってわかる?
ぼくはドラゴンの頭をエントチュに置いたんだ!」

「考えてみてよ」とキツネ小が言った。「僕たちの中には冒険する時間がない人もいる。大きな責任を負っていたり仕事があったりするんだ。生活の手段ってやつだよ。わかる?」

「ヘーイ、ぼくの仕事はドラゴンを殺すことだったんだ!!」ちっぽけなウサギが叫んだ。目を瞬かせ、木から木へ、沼から沼へと半狂乱に跳ね回りながら。「やつの鼻は大きな責任だった!! やつの煙たい息はぼくが考慮すべき問題だった!! ぼくはあそこに行くだけでタクシー代に50ドル払った。これは大きな大きな試練だった。君はぼくにかなわない。批難できない。ぼくの英雄性は絶対的に非の打ち所がない。ぼくの手段全体が、絶対的にアンズ不能だ。レスターに聞いてみて」

「レスターって、誰?」とキツネ小が聞いた。

「レスターはタクシーの運転手さ! 彼はドウェムジーズアレイの基地に駐車したんだ!!」 ウサギはスーパーコンピュータのスクリーンセーバーみたいに狂ったように飛び跳ねた。「ドウェムジーに聞いて!!」、

「ふうん」とキツネ小が言った。キツネ大の方を振り向いて見ると、彼はまっすぐ腰掛けて遠くを見つめていた。「えっ、ドウェムジーズアレーに駐車場があるの?」

そうとも!! それにプレッツェルスタンドも!!」

「だけど隊列なんでしょ? それがチュロを売ってるわけ?」

チョコラバだ!!」ウサギが言った。

「じゃあ暗闇で光る紐は売ってる? 髪に付けたり、手に持ったりするやつ——

「ブレイドクエスト!!」

「セールスマンのコミッションの分け前をもらうべきだよ」キツネ小が言った。「みんな君がドラゴンを殺すのを見に来たわけでしょ?」

「しかーし!! チョコラバを引っ張り出すやっとこはぼくがやってるわけじゃない」

「言っただけだよ。殺すところは君がやってるわけだよね。だったら君は分け前をもらう権利がある」

「あっ、しまった!! お気に入りのレタスをドウェムジーズアレイに置いてきた!!」ウサギが金切り声を上げ、揺れるオークの木の間を儀式用サーベルみたいにくるくる回った。遠くから「それともレスターのトランクかも?」と言った。

「ちょっとじっとしてられないの??」キツネ小が言った。

「僕のラジオは」キツネ大が一瞬生気を取り戻して言った。「ピックアップの中だ」。彼の目は相変わらずぼんやりしていた。彼の視線は震えた後に止まり、別な時間の別な場所を思い出していた。メリーランドへのドライブ 。ライオネル・リッチーの声がはっきりと聞こえる。ワイパーは動くのが少し早すぎる。家に車をつける。母親が戸口に出迎える。彼女はすごくふわふわしたキツネだ。涙とメーキャップ。

背もたれにどすんと寄り掛かった。「あのヤマアラシは私のプリセットを変えたに違いない」

ウサギはベンチのひじかけに飛び乗って、近くで話した。「しかし!! すぐにぼくはドラゴンの頭とドラゴンの舌のジュースを楽しむだろう!!」ウサギは静かに座って優しく手を握り合わせた。

「(シナモンバーみたいな味だといいんだけど)」ウサギが心から囁いた。

「シナモンなら好きだ」とキツネ小が言った。「僕もいつか君と一緒に殺しに行きたい」

「そうすべきだね」とウサギは言い、目を輝かせた。

「よだれだ。よだれを出してるんじゃない?」

「もちろん!!」ウサギは興奮して目からスティッキーウィップが飛び出した。(スティッキーウィップについては後の補足に書く。私が忘れているようだったら教えてほしい。ジョリー・パトリック・ソブゴブリンの「純粋主義者 のための新しい網膜クリームの概要」も参照。動物の飾り付きのクリップを置いているとこならどこでも手に入る。)

「ああ、すっかり興味を引かれちゃった。全部聞きたいね」キツネ小がきっぱりと言った。「エントチュについて話してよ。ああ、それにドウェムジーのことも。誰なの? 彼を動かしているものは何? それから僕がまだついていっているようなら、ウサギを動かしているものが何なのか教えて。そして僕たちの手を取って、なくしたトラックの試練を導いてほしい。僕は他のなによりも慰めを必要としてる。今だったら宗教だって信じるよ。君の勇敢さと君からにじみ出る達成感を僕は求めている。パイプは持ってる? 僕たちが結ぶ儀式の道具になるよ」

それからウサギはドウェムジーと、ドウェムジーの伝説と、ドウェムジーのやり方について詳しく説明しはじめた。ドウェムジーの話の多くと同様、ウサギの話は装飾だらけだった。スモッチキス、私だけが語るべき微妙な話があるのだ。

ドウェムジーが誰なのか決して聞かないでほしい。彼は明らかに黒幕で、その居場所や本当の素性を決して明かさない。彼は王国を持っている。彼は火の鬼を生み出した。馬はどこ にいても彼の臭いを感じ取る。なにより、彼は官能的な快楽を知っている。そしてこれが・・・

これが彼のアレイだ。

 

ドウェムジーズアレイ

Dwemthy's Array has charmed and tormented the village folk for centuries.

「ドウェムジーズアレイは最高だ!!
驚きで染めてくれ!!」

「こいつは血の付いたパズルだ」

「演奏しながら俺は、耳を聾するスタンディングオベーションと深い個人的な涙の間を漂っていた」

あなたはドウェムジーズアレイの入り口に立っている。あなたはアレイの奥深くにいて死にかけているウサギだ。

 class Dragon < Creature
   life 1340     # タフさの度合い
   strength 451  # 逆巻く血脈
   charisma 1020 # 歯を見せる笑顔
   weapon 939    # 炎の息
 end

激しく渦巻く溶岩が不協和音を立てて坑道を通りドウェムジーの森の永遠の天蓋の中に深く入り込み・・・飢えた野生のストーキュパインの腹から 脆い夜の叫びが聞こえ・・・グラハムクラッカーを食べてお昼寝したすぐあとの湿ったガチョウの子を食べる・・・正式には孤児だが自動車販売代理店のコングロマリットの所有する傘に守られ た飢えているカバの中・・・どろどろした青いエリクサーの蓋をしていない小瓶の下に・・・とどまりつづける・・・これまで・・・乱されることのな かった・・・ドウェムジー!!!

Luck and mother nature.

「自分の幸運をそんなに鼻にかけるものじゃないよ・・・そんなのいつでもなくなってしまう」

「実際はそうじゃない。幸運は魅力があって、人々をヒーローの目で見るときにやってくるんだ。そして木の精と母なる自然が幸運を与えてくれるんだ」

「僕がドラゴンなら、間違いなく木の精と母なる自然を最優先の仕事として殺すね」

ドウェムジーズアレイがわからないなら、それはドウェムジーの問題だ。彼は私たちの人生を複雑にするためにこのゲームをデザインしたのだ。単純なものだったら、私たちが腕に大切に抱 いて畏敬の念を感じる冒険とはならないだろう。

ドウェムジーズアレイにはとても深く曲がりくねった歴史がある。単純に「ドウェムジーズアレイ」と繰り返すだけでは信任状を得るのに十分ではない。私についてきて欲しい。何年かさかのぼ り、それがメタプログラミングとイルカで始まった60年代に連れて行ってあげよう。

あなたはメタプログラミングというのはファックス機の間で私用の電話をしたときにはじめて耳にしたハッカーの言葉だと思うかもしれない。ほんとのところ、真実 はそれよりもっと奇妙だということを話すために私はここにいる。メタプログラミングはイルカのいるところでドラッグをやっていたときに生まれたのだ。

60年代にジョン・C・リリーという多産な科学者が、体の仕組みを調べようと自分の感覚を材料に実験し始めた。私はこれに関係がある。道の真ん中にパイを持って立っているとき、あるいは聖堂の中に隠れているときに、私はこれを良くやる。私は自分自身を調べるために立ち止まる。これはほとんど不可能なことが証明された。私は罫線入りのノート3ページを代数式で埋めたが、そのどれも何も説明しはしなかった。ついでながら、パイというのは、数学的にとても容易に表現できる。

しかし科学者のリリーは実験を別の方向に進めた。彼はイルカと一緒にいるときにLSDを摂った。ときには暖かい海水で満たされた暗く悲痛な隔離タンクの中で。 すごく寒々としている。しかしそれは科学だったのだ! (彼が犯罪者だとは考えないことだ。1966年までは、Sandoz Laboratoriesが誰でも関心のある科学者にただでLSDを配っていたのだ。)

ドラッグ、イルカ、そして喪失。それがリリーの探索をメタなものに向けた。彼は、人とコンピュータを比較するメンタルプログラミングに関する本を書いた。あなたは次の引用を読む間に摂取するものを選んでいい——ほとんどの場合ひとつまみの塩に手を伸ばすだろう——しかし 芝生の上でグレートフルデッドのショーがあったり、熱狂的な人たちが地下室にあふれたりすることはないと請け合おう。

人が学ぶことを学ぶとき、人はモデルを作り、シンボルや、アナロジーを使い、メタファーを作り、つまり、言語や数学やアートや政治やビジネスなどを作り、利用する。脳(皮質)のサイズの上で大きな部分 を言語とそれにかかわる部分が占めている。学ぶことを学ぶこと、シンボル、メタファー、モデルといちいち繰り返すのを避けるため、これらの働きの基本になっているアイデア をメタプログラミングという記号で表すことにする。

ジョン・C・リリー、人間バイオコンピュータにおけるプログラミングとメタプログラミング、
ニューヨーク、1972年

私たちは学ぶ。しかし最初に学ぶことを学ぶ。私たちは心の中にプログラミングをセットアップし、それがプログラミングをさらに推し進めるための道となる。(リリーは 主として、彼がバイオコンピュータと呼ぶ脳と神経システムのプログラミングについて話している。)

リリーのメタプログラミングというのはむしろ、心象を与えるとか、自分自身を再構築するといったことだった。このような思考は、シャーマニズムに手を出し、タロットカードの上に手をかざし、空手の練習のために早起きする人々 に直接繋がるものだ。メタプログラミングはニューエージだと言 えるかもしれないが、それは最近では古き良きナード性とともに寝袋の中に収まっている。(あなたがGoogleで「C++ Metaprogramming」と検索してここに来たのなら、もう少し我慢してほしい。ただあなたにその検索をさせた神経経路は燃やしてしまってくれ。どうもありがとう。)

メタ自体は著者の時代でも違いなく語られている。

現実に対する感覚的反応というのはすべて、現実の解釈だ。甲虫もサルも彼らの世界を明らかに解釈している。そして彼らが理解したものに基づいて行動している。私たちの 身体的感覚はそれ自体解釈の器官なのだ。私たちを動物と区別しているのは、それらの解釈を解釈できるという私たちの能力だ。その意味で、人間の言語はすべてメタ言語なのだ。それは我々の体、我々の 感覚器官の「言語」の二次的な反映なのだ。

テリー・イーグルトン、理論のあと、ロンドン、2003年、第3章

その意味で、プログラミング自体メタ言語だと言うことができる。すべてのコードは、行動の言語を、まだ行われていないが間もなく行われるプランの言語を語る。マシンの中の役者 たちの舞台演出だ。私は以前これ をセンチメンタルに捉えていた。

しかし今では私たちの研究も進み、メタプログラミングの世界へと歩を進めているが、恐れることはない。それは依然としてあなたが見てきたRubyと違わない。それがドウェムジーがあなたにそれを押しつけることに呵責を感じない理由だ。すぐにそれは、足し算や引き算と同じくらい簡単にわかるようになる。最初それは、顔の方に飛んでくる蛍をはじめて見 たときのように、強烈に明るく見えるかもしれない。それから、それはオハイオでの暮らしをずっと良くしてくれる小さな揺れる光になる。

メタプログラミングとはコードを書くコードを書くということだ。しかしそれはM・C・エッシャーがスケッチするようにではない。プログラムは前に戻って自分自身を上書きすることはないし、画面から飛び出してあなたの手からキーボードをひったくることもない。それよりはずっと小さなことだ。

それはむしろあなたがサーカスで手に入れた小さなオレンジ色の錠剤に似ている。それを口に入れると、コーティングが溶けて、歯の裏側で大きな柔らかいスポンジのブロントサウルスが出てくる。それがあなたの舌を滑り降りて自由に飛び回り、草地をはしゃぎ回 って、「パパ!」と叫ぶのだ。そしてそれ以来、彼がイライラしてトラックを襲うときには、そのトラックはきれいな火花を散らすことだろう。

誰かが小さなオレンジ色の錠剤を水道の下に置いたとする。自分の舌の上にではなく、水道の下にだ。これは別な変化をもたらす。泣き叫ぶスポンジの八つ子を生む。へその緒や何やかや。それでもトラックを片づけるのには手頃だ。しかしまったく違った種類のシャモアだ。そしてある日、この8匹は、バイオリン演奏会 に出てパパに涙を流させる。

メタプログラミングはコードを錠剤の形に詰め込み、ほんのちょっと水を垂らすだけで広がりはじめる。さらに重要なのは、錠剤の反応をコントロールできるということで、鱗 のあるのっそりしたブロントサウルスが作られるようにできる。あるいはもちろん八つ子でもいい。あるいはお針子でも。あるいは猫の脳みそでも。あるいはドラゴンでも。

 class Dragon < Creature
   life 1340     # タフさの度合い
   strength 451  # 逆巻く血脈
   charisma 1020 # 歯を見せる笑顔
   weapon 939    # 炎の息
 end

これはまだメタプログラミングではない。ただの錠剤だ。メタプログラミングの結果だ。いったん立ち止まって怪物自体を見てみることにしよう。メスと顕微鏡を使って肉体の内部へと進む前に。

Dragon はクラスだ。もう何度も見ているだろう。DragonCreature クラスの子孫だ。

目を上げて、私を見て。Creature クラスはメタプログラミングコードを含んでいる。あなたはRubyのどこででも使えるメタプログラミングコードを書くことができる。CreatureDragonの中でも、Stringの中でも、Objectの中でも、どこででもだ。ここで挙げる例では、メタコードの最も一般的な形態である、自分のクラスの中でだけ使うメタプログラミングに焦点を当てる。

Dragonの特徴のそれぞれはただのクラスメソッドだ。 これは次のように書くこともできる:

 class Dragon < Creature
   life( 1340 )     # タフさの度合い
   strength( 451 )  # 逆巻く血脈
   charisma( 1020 ) # 歯を見せる笑顔
   weapon( 939 )    # 炎の息
 end

括弧を取った方がすっきりするので、括弧は省略することにする。メソッドをいくつかまとめて使うのではっきりさせたいという時だけ括弧を使うようにしよう。

Creatureのコード

横隔膜のところでスライスしてCreatureの内部を見せよう。このコードをdwemthy.rbという名前で保存して。

 # ドウェムジーズアレイの生命力の中心
 class Creature

   # このクラスのメタクラスを取得する
   def self.metaclass; class << self; self; end; end

   # 特徴(trait)を素敵できれいに表現するための先進的なメタプログラミングコード
   def self.traits( *arr )
     return @traits if arr.empty?

     # 1. それぞれの変数にアクセサを用意する
     attr_accessor *arr

     # 2. それぞれのtraitにクラスメソッドを追加する
     arr.each do |a|
       metaclass.instance_eval do
         define_method( a ) do |val|
           @traits ||= {}
           @traits[a] = val
         end
       end
     end

     # 3. それぞれのモンスターについて、initializeメソッドはそれぞれのtraitの
     #    デフォルトの値を使う
     class_eval do
       define_method( :initialize ) do
         self.class.traits.each do |k,v|
           instance_variable_set("@#{k}", v)
         end
       end
     end

   end

   # Creatureの属性はリードオンリー
   traits :life, :strength, :charisma, :weapon
 end

最後の行に注目してほしい。つまりtraits をセットアップしている行だ。その前にあるコードはすべてtraits クラスメソッドをセットアップしている。これは前の章のLotteryTicketを思い出させる。

 class LotteryTicket
   attr_reader :picks, :purchased
 end

 traitsattr_reader のどちらも単なるクラスメソッドだ。attr_readerLotteryTicketで使われたとき、裏ではメタプログラミングが動き出して、風船を膨らませ、インスタンス変数 @picks@purchased に対するリーダーメソッドを作り出していた。

traitsメソッドのコードは私がずっと仄めかしていたメタプログラミングだ。コードのコメントが、traitsを追加するときにたどる3つの段階を明らかにしている。

  1. traitsのリストがattr_accessorに渡され、それぞれのインスタンス変数に対するリーダーのコードとライターのコードを生成する。
  2. それぞれのtraitに対してクラスメソッドが追加される(たとえばlife クラスメソッドが:lifeに対して追加される)。これらのクラスメソッドはあなたがtraitsattr_accessorを使うのと同じようにクラス定義で使われる。このようにしてそれぞれのcreatureとtraitの組に対してポイントを指定 できるようになる。
  3. 初期化メソッドを追加して新しいモンスターのプロパティをセットアップし、適切なポイントを与え、そして——パワーアップ! パワーアップ! モンスターが生きてるぞ!

この3ステップの素晴しいところは、あなたがRubyにモンスターのコードをどう書けばいいのか教えているということだ。Rubyがtraitsのところに来ると:

 class Creature
   traits :life, :strength, :charisma, :weapon
 end

Rubyは裏でコードを埋め、トゲだらけの緑色の心臓を移植し、プルコードを引いて体をジャンプスタートさせる。RubyはCreature クラスのメタプログラミングを使い、様々なメソッドを作り出し、traitsリストを次のような形に展開する:

 class Creature

   # 1. リーダ / ライタ メソッドを用意する
   attr_accessor :life, :strength, :charisma, :weapon

   # 2. creatureの中で使う新しいクラスメソッドを追加する
   def self.life( val )
     @traits ||= {}
     @traits['life'] = val
   end

   def self.strength( val )
     @traits ||= {}
     @traits['strength'] = val
   end

   def self.charisma( val )
     @traits ||= {}
     @traits['charisma'] = val
   end

   def self.weapon( val )
     @traits ||= {}
     @traits['weapon'] = val
   end

   # 3. initializeはそれぞれのtraitにデフォルトのポイントを設定する
   def initialize
     self.class.traits.each do |k,v|
       instance_variable_set("@#{k}", v)
     end
   end

 end

そうすると、トランプに印刷したらぴったりなくらい短いこの6行のDragon のコードを、Rubyは喜んで受け入れるようになる。

 class Dragon < Creature
   life 1340     # タフさの度合い
   strength 451  # 逆巻く血脈
   charisma 1020 # 歯を見せる笑顔
   weapon 939    # 炎の息
 end

 

Eval - 最小のメタプログラマ

メタプログラミングのコードは普通のRubyではあるが、追いかけるのは難しいかもしれない。この時点であなたの目が眼窩の中でぐるぐる回り、膝が動かなくなっていたとしても理解できる。上のコードで一番トリッキーなのは、instance_evalメソッド とclass_evalメソッドを呼んでいるところだ。私がevalについて説明している間、 関節にタイガーバームでも塗っておくといい。

私たちはメタプログラミングの話をしている。コードを書くコードを書くということだ。evalメソッドはこの横町に出入りしている。さすらいのevalはあなたが文字列の中に収めたコードを受け取ってそのコードを実行する。

 drgn = Dragon.new
 # これは次のように書くのと同じだ・・・
 drgn = eval( "Dragon.new" )
 # あるいは、こう書いてもいい・・・
 eval( "drgn = Dragon.new" )

穴の開いたプログラムを書いてみることにしよう。新しいDragonを作るプログラムを書くかわりに、Dragonが入る部分を穴にしておくのだ。

 print "どのモンスタークラスと戦いますか? " 
 monster_class = gets
 eval( "monster = " + monster_class + ".new" )
 p monster

(訳注: 変数monsterが前に使われていないとp  monsterが未定義の変数エラーになる)

このプログラムはモンスターの名前を尋ねる。あなたがDragonとタイプすると、monster_class 変数に文字列"Dragon"が設定される。evalの中でいくつかの文字列がつなぎ合わされて、"monster = Dragon.new"という文字列ができる。そしてevalが実行されると、monster変数にはDragon オブジェクトが設定され、戦いの準備ができる。

これはすごい! いまやプレーヤーがモンスターを選べるようになったのだ! もちろんこれはプレーヤーが実在するモンスタークラスを指定してくれることを当てにしている。彼らがBotanicalWitch (植物女)とタイプしてBotanicalWitchクラスがなかったなら、彼らは顔に例外をたたきつけられることになる。

簡単に言うと、evalは実行するその場でコードを作ることができるのだ。これは有用であり、かつ危険でもある。

Creatureクラスのメタプログラミングで使われていたinstance_evalメソッドとclass_evalメソッドは、ただのevalと若干異なっている。これらの2つの特別なメソッドはeval と同じようにコードを実行させるが、しかしクラスやオブジェクトの中に入り込んで、そこでコードを実行するのだ。

 # instance_evalメソッドはオブジェクトのインスタンスメソッドの中であるかのように
 # コードを実行する
 irb> drgn = Dragon.new
 irb> drgn.instance_eval do
 irb>   @name = "Tobias" 
 irb> end

 irb> drgn.instance_variable_get( "@name" )
   => "Tobias" 

 # class_evalメソッドはクラス定義の中であるかのようにコードを実行する
 irb> Dragon.class_eval do
 irb>   def name; @name; end
 irb> end

 irb> drgn.name
   => "Tobias"

上で見てわかるとおり、instance_evalメソッドとclass_evalメソッドは文字列のかわりにコードブロックを取ることもできる。それがドウェムジーズアレイでものごとがなされる仕方なのだ。

 

人を見くびった解説や意味ありげな併記はもう十分だ——ドウェムジーズアレイはどこにあるんだ??

注意して歩いて——ここにドウェムジーズアレイの残りの半分がある!! このコードをdwemthy.rbに追加して。

 class Creature

   # このメソッドは戦いで受けたダメージを適用する
   def hit( damage )
     p_up = rand( charisma )
     if p_up % 9 == 7
       @life += p_up / 4
       puts "[#{ self.class }は魔法で#{ p_up }パワーアップした!]" 
     end 
     @life -= damage
     puts "[#{ self.class }は死んだ。]" if @life <= 0
   end

   # このメソッドは戦いの1ターンを行う
   def fight( enemy, weapon )
     if life <= 0
       puts "[#{ self.class }は戦うには死にすぎている!]" 
       return
     end

     # 敵を攻撃
     your_hit = rand( strength + weapon )
     puts "[あなたの攻撃は#{ your_hit }ポイントのダメージを与えた!]" 
     enemy.hit( your_hit )

     # 敵の反撃
     p enemy
     if enemy.life > 0
       enemy_hit = rand( enemy.strength + enemy.weapon )
       puts "[敵の攻撃で#{ enemy_hit }ポイントのダメージを受けた!]" 
       self.hit( enemy_hit )
     end
   end

 end

 class DwemthysArray < Array
   alias _inspect inspect
   def inspect; "#<#{ self.class }#{ _inspect }>"; end
   def method_missing( meth, *args )
     answer = first.send( meth, *args )
     if first.life <= 0
       shift
       if empty?
         puts "[ワオ。あなたはドウェムジーズアレイを全滅させた!]" 
       else
         puts "[準備して。#{ first.class }が現れた。]" 
       end
     end
     answer || 0
   end
 end

このコードはCreatureに2つのメソッドを追加する。hit メソッドは他のCreatureからの攻撃に対応する。fightはそのCreatureに対してあなたの一撃を加える。

あなたのCreature が攻撃を受けると、防御が働いて、charisma 値を使ってパワーアップする。この現象の背後にある秘密については聞かないでほしい。乱数が選択されて単純な算術が行われる。あなたが幸運なら、何ポイントかライフポイントが手に入る。@life += p_up / 4

それから敵の攻撃が来る。@life -= damage。これがCreature#hitメソッドの働く仕組みだ。

fight メソッドはまず自分のCreature が生きているか確認する。それから敵に対してランダムな攻撃を加える。敵は攻撃をしのぐと、反撃のチャンスを得る。これがCreature#fightメソッドの働く仕組みだ。

DwemthysArray についてはすぐに説明する。ほんとにするって。そうするのが楽しいんだ。しばらくhitしたりfightしたりしていよう。

 

あなたを登場させる。

あなたはこのウサギの派生物をいじり回してもいい。しかしドウェムジーの公式な範例では、そのコードは——そしてキャラクタ の全体が——明示的に以下のように記述されている。これをrabbit.rbという名前で保存しよう。

 class Rabbit < Creature
   traits :bombs

   life 10
   strength 2
   charisma 44
   weapon 4
   bombs 3

   # 小さなブーメラン
   def ^( enemy )
     fight( enemy, 13 )
   end
   # 英雄の剣は無制限だ!!
   def /( enemy )
     fight( enemy, rand( 4 + ( ( enemy.life % 10 ) ** 2 ) ) )
   end
   # レタスはあなたの体力を上げ、余った葉っぱは敵の顔に飛んでいく!!
   def %( enemy )
     lettuce = rand( charisma )
     puts "[ヘルシーなレタスであなたの体力が#{ lettuce }ポイント回復した!!]" 
     @life += lettuce
     fight( enemy, 0 )
   end
   # 爆弾。ただし3つしか持っていない!!
   def *( enemy )
     if @bombs.zero?
       puts "[うわっ!! 爆弾が切れた!!]" 
       return
     end
     @bombs -= 1
     fight( enemy, 86 )
   end
 end

あなたには4つの武器がある。ブーメラン。英雄の剣。レタス。それに爆弾だ。

はじめるには、irb を起動して、ここまでで作ったライブラリをロードしよう。

 irb> require 'dwemthy'
 irb> require 'rabbit'

それから、あなた自身を展開する。

 irb> r = Rabbit.new
 irb> r.life
   => 10
 irb> r.strength
   => 2

いいぞいいぞ。

ウサギはスキューバアルゼンチンと戦う!

あなたはシートベルトもせず、香水を付けただけでドウェムジーズアレイに突入するむわけにはいかない。悪魔のカドリールを慎重に進む必要がある。あるいは南の藪と石炭の迷宮を通り抜ける必要がある。

とりあえずは、こっそり水路の白い残留物に隠れよう。そしてScubaArgentineに忍び寄るのだ。

 class ScubaArgentine < Creature
   life 46
   strength 35
   charisma 91
   weapon 2
 end

戦いを始めるには、あなたを1つと、ScubaArgentineを1つ作る。

 irb> r = Rabbit.new
 irb> s = ScubaArgentine.new

よし、小さなブーメランで攻撃だ!

 irb> r ^ s
 [あなたの攻撃は2ポイントのダメージを与えた!]
 #<ScubaArgentine:0x808c864 @charisma=91, @strength=35, @life=44, @weapon=2>
 [敵の攻撃で28ポイントのダメージを受けた!]
 [Rabbitは死んだ。]

なんてことだ!! 私たちのウサギが死んでしまった!!

無慈悲な展開だ。だけどあなたにウサギの国に帰ってくれと言うわけにもいかない。あなたが死ななかったふりをして、新しいウサギを作ることにしよう。

 irb> r = Rabbit.new

 # ブーメランで攻撃!
 irb> r ^ s

 # 英雄の剣が切り裂く!
 irb> r / s

 # レタスを食べて体力が回復!
 irb> r % s

 # 爆弾が3つある!
 irb> r * s

これはなかなかかっこいいと思わない? rabbit.rbのコードは算術記号を置き換えてRabbitだけの特別な使い方をしている。Rubyでは算術オペレータの振る舞いを変えることができる。なんにしても、算術オペレータはメソッドにすぎないのだ!

 # ブーメランは通常はXORオペレータだ。
 irb> 1.^( 1 )
   => 0

 # 英雄の剣は通常は数を割る。
 irb> 10./( 2 )
   => 5

 # レタスは割り算の余り。
 irb> 10.%( 3 )
   => 1

 # 爆弾はかけ算だ。
 irb> 10.*( 3 )
   => 30

そうするのが適切である場合には、自分のクラスで算術オペレータを使って構わない。Rubyは算術オペレータをいろいろなクラスで使っている。たとえば配列もいくつかの算術オペレータを持っている。ri Arrayでインスタンスメソッドの一覧を出せば見ることができる。

 # プラスオペレータは2つの配列を組み合わせて1つの配列にする。
 irb> ["D", "W", "E"] + ["M", "T", "H", "Y"]
   => ["D", "W", "E", "M", "T", "H", "Y"]

 # マイナスは2番目の配列の要素をすべて最初の配列から取り除く
 irb> ["D", "W", "E", "M", "T", "H", "Y"] - ["W", "T"]
   => ["D", "E", "M", "H", "Y"]

 # かけ算は配列の要素を繰り返す
 irb> ["D", "W"] * 3
   => ["D", "W", "D", "W", "D", "W"]

あなたはこれが数学的にどういう意味があるのかと不思議に思っているかもしれない。配列に3を足したらどうなるのか? 文字列に数を足したら? Rubyはどう反応するのだろう?

これらのオペレータが単なるメソッドであることを思い出してほしい。これらのオペレータは読める言葉になっていないので、それが何をするのか言い当てるのは少し難しくなる。riを使おう。あなたは これらのオペレータがしばしば他の読める名前を持ったメソッドと同じであることに気付くだろう。オペレータとメソッドで好きな方を選んで使えばいい。よりわかりやすいと思える方を。

 # 割り算するのにオペレータメソッドを使うか・・・
 irb> 10 / 3
   => 3

 # ・・・あるいは読めるメソッドを使うか?
 irb> 10.div 3
   => 3

Rabbitの剣が割る仕方も同じことだ。

 

ドウェムジーズアレイの厳しい現実があなたを叩き潰そうと待ちかまえている!!

最後のやつを酸素チューブを使ってプレイチョークをかけて片づけたら、アレイに入る時だ。私はあなたにやれるか疑問に思っている。あなたは戦斧を家に置いてきてしまった。あなたが弱いやつ相手に爆弾を全部使っ たりしていないことを願っている。

あなたには6匹の敵がいる。

 class IndustrialRaverMonkey < Creature   # 工業的乱痴気モンキー
   life 46
   strength 35
   charisma 91
   weapon 2
 end

 class DwarvenAngel < Creature   # ドワーベンエンジェル
   life 540
   strength 6
   charisma 144
   weapon 50
 end

 class AssistantViceTentacleAndOmbudsman < Creature   # 副アシスタント触手オンブズマン
   life 320
   strength 6
   charisma 144
   weapon 50
 end

 class TeethDeer < Creature   # 歯ジカ
   life 655
   strength 192
   charisma 19
   weapon 109
 end

 class IntrepidDecomposedCyclist < Creature   # 恐れを知らぬ腐りかけのサイクリスト
   life 901
   strength 560
   charisma 422
   weapon 105
 end

 class Dragon < Creature    # ドラゴン
   life 1340     # tough scales
   strength 451  # bristling veins
   charisma 1020 # toothy smile
   weapon 939    # fire breath
 end

これがドウェムジーズアレイに生き、呼吸しているモンスターたちだ。彼らがどうやってここに来たのかは知らない。誰も知らないのだ。IntrepidDecomposedCyclist はきっと10段変速に乗ってきたんだろうと思うが、他のやつについてはわからない。

どうしても知る必要があるというのなら、他のやつはここで生まれたのだということにしておこう。先に進んでもいい?

ドウェムジーズアレイに深く入っていくほど、挑戦はどんどん難しくなっていく。

 dwary = DwemthysArray[IndustrialRaverMonkey.new,
                       DwarvenAngel.new,
                       AssistantViceTentacleAndOmbudsman.new,
                       TeethDeer.new,
                       IntrepidDecomposedCyclist.new,
                       Dragon.new]

闘い進むにつれ、モンスターが次々と現れてくる。あなたが素早ければ、天使のかぎ爪に肩を貫かれることなく、恐ろしい話を持って逃げ帰ることができるかもしれない。

でははじめよう。

 irb> r % dwary

ああ、それから「私は死ぬには若すぎる」というのはなしだ。そんなくだらないことは聞きたくない。私はあなたに若き亡者たちを侮辱させるつもりはない。彼らは私たちの未来だ。我々の未来が終わったら、それが来るのだ。

The rabbit has changed us.

「行こう。あのウサギは何て?」
「彼はドラゴンを殺したそうだ」

「ワオ。それはすごい偉業だな。彼はこの日を一生忘れることはないだろう」
「日記を持ってなければ、ぜひ手に入れるべきだね」

「みんなぼくがいかに幸運か噂してる!」

 

ドウェムジーズアレイの作り方

風が止むところまで早送りしよう。ドラゴンは撃破された。卑しき輩たちはひれ伏している。私たちはあなたを好きだ。あなたに忠誠を尽くす。

しかしあなたの鼓膜を食い破っているムカデは何? 指でほじっても、そいつを追い出すことができない! なんてことだ! 地獄のドウェムジーズアレイがまた現れた。正体を現せ、ドウェムジー!

ここにアレイの正体を暴露しよう。

 class DwemthysArray < Array
   alias _inspect inspect
   def inspect; "#<#{ self.class }#{ inspect }>"; end
   def method_missing( meth, *args )
     answer = first.send( meth, *args )
     if first.life <= 0
       shift
       if empty?
         puts "[ワオ。あなたはドウェムジーズアレイを全滅させた!]" 
       else
         puts "[準備して。#{ first.class }が現れた。]" 
       end
     end
     answer || 0
   end
 end

今では、あなたも継承に慣れ親しんでいると思う。DwemthysArray クラスはArray を継承し、Array のように振る舞う。あんなミステリーであるにしては、中身は驚くほど簡単だ。そうじゃない?

つまりはArrayということだ。モンスターでいっぱいの。しかしここで追加されているコードは何なのだろう?

 

Inspect

inspectメソッドはドウェムジーズアレイに本当に必要なものというわけではない。これはアレイのお客様へのサービスとしてドウェムジーが追加したものだ。(多くの人が彼をねじけていると言い、多くの人が彼を陰鬱だと言うが、彼が私たちのためにしつらえてくれた処置に敬意を感じないとしたら、私たちは無知のそしりを逃れないだろう。)

Rubyのオブジェクトはみなinspect メソッドを持っている。これはObject クラスで定義されているので、親から子へと受け継がれ、生まれたばかりのちっぽけなオブジェクトにもみんなあるのだ。

 irb> o = Object.new
   => #<Object:0x81d60c0>
 irb> o.inspect
   => "#<Object:0x81d60c0>"

これに気付いた? irbでオブジェクトを作ると、このごちゃごちゃした#<Object>というのが転げ出てくる! これはオブジェクトの小さな名札だ。inspect メソッドは名札を作る。名札はただの文字列だ。

 irb> class Rabbit
 irb>   attr_accessor :slogan
 irb>   def initialize s; @slogan = s; end
 irb>   def inspect; "#<#{ self.class }は「#{ @slogan }」と言う>"; end
 irb> end

 irb> class FakeRabbit < Rabbit
 irb> end

 irb> Rabbit.new "ぼくはドラゴンの顔を吹っ飛ばした!!" 
   => #<Rabbitは「ぼくはドラゴンの顔を吹っ飛ばした!!」と言う>
 irb> FakeRabbit.new "かくかくしかじか・・・" 
   => #<FakeRabbitは「かくかくしかじか・・・」と言う>

これは実はirb が言い返しているのだ。あなたがirbで何かのコードを実行するとき、そのコードが返す値がinspect(検査)される。これは便利だ。これはあなたとirbの間でちょっとした会話をしているのだ。irbはあなたの言ったことをただ繰り返し、あなたが自分で言ったことを確認できるようにしている。

あなたは自分のRubyプロンプトを簡単に作ることができる。

 loop do
   print ">> " 
   puts  "=> " + eval( gets ).inspect
 end

このプロンプトでは1行より長いRubyコードを書くことはできない。しかしこれがインタラクティブRubyの本質部分なのだ。どう思う? 最近学んだ2つのコンセプトが、もっとも好ましい仕方で1つになっている。evalは打ち込まれたコードを受け取ってそれを実行する。そしてevalのレスポンスがinspectされる。

さて、irbであなたがモンスターと闘っていると、ドウェムジーズアレイがinspectされ、まだ残っているモンスターを返す。

The foxes eat out.

「キャットマンブルーバーガーには何が入ってるの?」「ネズミとオニオンソテー」

「じゃあ焼いたチーズだけもらえない?」
「チーズは切らしてる」
「僕はマッシュポテトとインゲン豆をカップ一杯」

——ペカンの実をちりばめたチキンがないのはまだわかるけど——しか しオムレツがないって??  ここの動物たちがおいしいニラを食べたことないなんて言わないでよ」
「このハニーローストしたフクロウの頭蓋はすごくいけるよ!!!」


メソッドが見つかりません

あなたが「ディアドラ!」と呼んだら10人が答えるというのは嫌じゃない? Rubyではそういうことは決して起こらない。あなたがdeirdreメソッドを呼ぶと、ただ1つのdeirdreメソッドが答える。2つのメソッドの名前を同じにすることはできないのだ。2番目のdeirdreメソッドを付け加えたとしたら、最初のは消えてしまう。

しかしいろんな名前に答えるメソッドなら作ることはできる。

 class NameCaller
   def method_missing( name, *args )
     puts "あなたは'" + name.to_s + "'を呼んで言う:" 
     args.each { |say| puts "  " + say }
     puts "しかしそこには誰もいない。" 
   end
   def deirdre( *args )
     puts "ちょうどそこにいたdeirdreにあなたは言う:" 
     args.each { |say| puts "  " + say }
     puts "そして彼女はその一瞬一瞬を楽しんでいる。" 
     puts "(私は彼女があなたのことを詩人だと思ったと思うよ。)" 
   end
 end

上のdeirdre メソッドを呼んだとき何が起こるか、あなたはわかることと思う。ディアドラはその一瞬一瞬を、あなたの目もくらむような詩的な声の響きを楽しむことだろう。

しかしsimonを呼んだらどうなるのだろう?

 irb> NameCaller.new.simon( 'ねえ?', 'ねえ? サイモン?' )
 あなたは'simon'を呼んで言う:
   ねえ?
   ねえ? サイモン?
 しかしそこには誰もいない

そう、method_missing というのは留守番電話みたいなもので、メソッド呼び出しを横取りするのだ。ドウェムジーズアレイではみんな自動転送サービスを使っており、あなたがアレイを攻撃すると、その攻撃はアレイにいる最初のモンスターへと送られる。

 def method_missing( meth, *args )
   answer = first.send( meth, *args )
   # ... コードを省略 ...
 end

気をつけて! 痩せたちっぽけなmethod_missing が応戦相手を割り当てた!

 

4. はっきりさせておこう。ヤマアラシは今、海の方にいる

The porcupine and his kite.

 

 

「あまり高く行かないで」

 

5. 歩いて、歩いて、歩いて、歩いたりとか

2匹のキツネたちの周りで夜が更けていった。歌うフクロネズミでいっぱいの路地を抜け、表通りではしわくちゃの遊び着を着てブリーフケースを持ったシマウマたちがぶつかりながら通り過ぎ ていった。彼らは歩き続けた。

店はもう、うねった金属製のシャッターを下ろしていた。溝からはい出したコロオギが小銭を押していた。

Why such hard feelings?

「マルコス大統領に対して君のような悪感情を呼び起こすのは難しいよ」

「彼は私の家族の財産を横領してないし、妹を無理に妻にして私を家族から遠ざけてもいないし、私のパイロット免許を取り上げてもいなければ、私の一輪車のタイヤをパンクさせてもいない」

「あいつはおじいさんが引っ越す時、小型グランドピアノを運ぶのを手伝わなかったんだぞ!」

「なんにしても、あいつがひどい大統領だってことは認めなきゃいけない」とキツネ小が言った。「マルコス大統領がキツネの副大統領にウサギを選 ぶなんてどういう了見なんだろう」

「副大統領? あの眉毛のあるウサギのこと?」

「そうじゃなくて、大きなたらこ唇のやつさ」とキツネ小が言った。

しかし彼らの会話は、歩道の上の空に突然現れたそばかすだらけの猫の顔によって中断された。

At least they're still in the book...

「トラックを探してるの?」「うわっ、なに?」

「ああ、僕はこの本の別なキャラクタで、君たちの章をたまたま覗いていたんだ」「僕らはまだ本の中にいたの?!」

「ああ、今第7章だ。みんなRubyを勉強してるよ。素晴らしいことだ」
「みんな"Chunky Bacon"って言ってる?」
「ああ、そうだ!  僕らが発明したんだ!」

これはどういうことだ?

Will the book finish?

「この素敵な午後を君らのために台無しにしたくない・・・」
「・・・しかしホワイが本を書き上げるとは思えない」

「彼の妹が・・・彼の妹が自殺を図ったんだ・・・彼女はホワイに電話して・・・」
「そして言ったんだ。『来て! 私が生きている最後の夜なんだから! 』」

「キャー!」
「それは大変だ! 彼女は大丈夫なの?」
「ホワイがどれほど動揺していることかと思うよ」

ああ、これは面白い。さらなるメタ。

ブリクシーとキツネたちの議論をわざわざ描こうとは思わない。推測に過ぎないのだ。彼らに私の家族の事情がどうしてわかると言うんだ? 私は妹を愛している。ずっと昔から彼女を崇拝していた。(妹のクウィルのことだ。) 

数ヶ月前にとても辛いことがあって、私が普通でなかったことは認める。私は母の家の裏庭でプール脇の長椅子に横になっていた。ドクターペッパーを飲み、ドイツ風のチョコレートケーキを食べた。私は子供用のフォークで食べていた。他のフォークはみんな皿洗い器の中 で、それしかなかったのだ。フォークには 角が3つあった。

母がクウィルのことを話し始めた。あの子がズボンやバッグにどんなに金を使っていることかと。500ドルもするバッグ。それからこう言った。「それをなくしちゃうのよ。電話ですっかりハイになってるみたいだった」。(母はクウィルが麻薬を吸っていると思いこんでいた。)

母が時にどれほど観察が鋭いかということに気付いた。だから母が「私は実際あの子がコカインをやってるんじゃないかと思っている」と言ったとき、私は立ち上がってコーラを庭の向こうに投げ捨てた。

それは森のどこかに飛んでいった。私たちは長い間話していていたので、缶を投げたときには暗くなっていた。私は少し歩き回り、それから声の限りを尽くして叫んだ。

叔父のマイクがガラス戸を開けて立っていて、私を見ていた。彼はまったくオロオロして「OK、OK、私が・・・」みたいなことを言った。彼のグラスの中の紅茶が揺れ、そこら中に 飛び散った。そしてどこかへ行った。彼は人にものを言うのがあまりうまくなかった。彼はむしろたれこみ屋だ。そして大げさだった。

Moving along.

「じゃあ、先に進もう・・・」

「ただこの道を進むの?」

「あ・・・バスが来る・・・」

だから、すっかり正直に言うと、私は少しおかしくなっていた。ああ、狂っていたとも。私はそれに対処した。クウィルは定期的に電話をかけてくる。つまらない理由のために、私は滅多に彼女に電話しない。

加えて、彼女は結局自殺したわけではなかった。だからそれは問題ではない。誰に本当のことがわかる? 彼女はただウォッカをたくさん飲んだだけだ。そして彼女は体が小さかった。だからクウィルがウォッカをがぶ飲みするのを見ているのは怖かった。彼女は無理して飲んでいた。

しかし何で私はこんな話をしているんだ? これじゃ私が失望しているみたいに彼女に見えるだけだ。あるいは私が間抜けなように。

どうも脱線してしまったようだ。何の話だっけ? ブリクスはキツネたちがトラックを追跡するのを手助けしている。ああ、そういう話だった。

Frogs who save seats on the bus.

カエルがバスの座席を占めている

「このバスには乗れないよ」とキツネ小が言った。

「乗って乗って」とブリクスが言った。「何をためらってるの? ああ、カエルか。なに、ちょっと押し込めばいいよ」ブリクスが後ろから押した。

「ねえ」とキツネ大が言った。「こっちは階段に立ってるんだ、誰か詰めてよ!」

「通れた? 若いキツネ君?」とネコが言った。

「いや」とキツネ小が言った。「見えない? 運転手がずっと頭を振っている。僕はどうも不安だ。彼は僕たちを乗せたくないみたいだ」

「進んで」とブリクスが言った。彼はステップから下りて、バスの周りを歩き、プレキシガラスの窓から中を覗いた。「ああ、ちょっとわからない。カエルがたくさん乗ってるみたいだ」。彼は窓を叩いた。「ちょっと、詰めてよ!」

そしてそれがウィグズルの長距離バスに乗るということの現実だった。すごく競争が激しいのだ。朝のバスがあまりに混んでいるので、ホワイトカラーの動物たちはみんな夜の間カエルに席取りをさせているのだ。どういうものか、それでうまくいっているのだ。これが彼らのワークフローと経済の中心になっているのだ。

少しばかり想像力を働かせれば、パーセント記号が傾けたカエルの顔に見えるだろう。頭の中でイメージできた? それでは、文字列の中に居座っているカエルをお見せすることにしよう。

 # %s書式は文字列を入れるため。
 irb> "席は%sと%sによって占められている。" % ['カエル', '歯のあるカエル']
   => "席はカエルと歯のあるカエルによって占められている。" 

 # %d書式は数字を入れるため、%f書式は浮動小数点数を入れるためのもの。
 irb> frogs = [44, 162.30]
 irb> stats = "カエルは%d席を占めてブルークリスタルを%f払った。" 
 irb> stats % frogs
   => "カエルは44席を占めてブルークリスタルを162.30払った。" 

 # 書式制御は型について柔軟で、文字列を渡して数として書式指定することができる。
 irb> frogs = ['44', '162.30']
 irb> stats % frogs
   => "カエルは44席を占めてブルークリスタルを162.30払った。"

ここで見ているのはString クラスでの % メソッドの使用だ。このメソッドは文字列配列を取って、それを一緒にして新しい文字列を作る。配列の中の要素は(順番通りに)取り出され、確保してある席に置かれる。それが1日の始まりで、カエルはその役割を果たしたのだ。

 # String#%メソッドも他のメソッドのような呼び出し方ができる。
 irb> "ちょっと詰めてよ、%sさん。".%( '歯のあるカエル' )
   => "ちょっと詰めてよ、歯のあるカエルさん。" 

 # 文字列と配列の間にパーセント記号を置くもっと見栄えのいいやり方で呼んでみよう。
 irb> "これが君の今年1098番目のステートメントだ、%sさん。" % ['歯のあるカエル']
   => "これが君の今年1098番目のステートメントだ、歯のあるカエルさん。"

これはまたKernel::formatメソッドやKernel::sprintfメソッドとしても使える。(C言語には同じような働きをするsprintf メソッドがある。)

 irb> format "カエルは%d重に積み重なって、%dマイル/hで移動した。", 5, 56
   => "カエルは5重に積み重なって、56マイル/hで移動した。"

ほとんどの場合書式指定子%s (文字列)、 %d (整数) 、%f (浮動小数点数)だけで用が足りるだろう。 %pプレースホルダを使うと、オブジェクトのinspect が実行される。

そういうわけで、様々な種類のデータを組み立てて文字列を作る場合に、カエルの書式指定はとても便利だ。ri sprintfのページを見れば、あらゆる種類の書式指定子について学ぶことができる。ここでは簡単なヒントだけいくつか示 しておこう。

配列の要素を配列に入っているのとは違う順序で文字列の中に配置したいとしよう。そういう場合には、パーセント記号の後に番号を付けることで特定の要素を指定することができる(1$が最初の要素、2$が2番目の要素、という具合に)。

 irb> "このバスはあと%1$dカ所に止まります。%2$d時までにもう%1$dカ所です。" % [16, 8]
   => "このバスはあと16カ所に止まります。8時までにもう16カ所です。"

2番目のヒントは、それぞれの要素に対して文字数、つまり幅を指定できるということだ。要素がその幅より小さい場合は、余分な空白が要素の前に置かれる。詰め物をするわけだ。幅を負の数で指定すると、要素は左詰めになって、空白がその後に置かれる。

 # 30字幅
 irb> "バスの後部には: %30s。" % ['カエル']
   => "バスの後部には:                          カエル。" 

 # 左詰で30字幅
 irb> "バスの前部には: %-30s。" % ['カエル']
   => "バスの前部には: カエル                        。"

キツネ小はバスの運転手をずっと見上げていた。彼がバスに乗ろうとしなかったことを思い出して!

「何が問題なの?」とキツネ大が言った。「ただ中に乗って、通路に立ってればいいんじゃない?」

「ほんとにこのバスに乗るつもり? 運転手は手がないんだよ」とキツネ小がキツネ大の耳元でささやいた。「彼は手のかわりに吸盤がついてる」

「だから? 触手のある動物には運転ができないっていうの?」

「彼がハンドル操作でへましそうだってだけじゃない。あのたくさんの足をみんなペダルに載せてるんだ。どう見てもいい考えじゃないね。別なバスを探そう。ほら」

「彼はたぶんああやってずっと運転してきたんだよ。今になって急に事故を起こし出すっていうの?」

「バスは事故を起こすさ」キツネ小が言った。「起こすやつは。あれは事故を起こしそうな気がする」

「くだらない!」そしてキツネ大は運転手に向かって大声で言った。「ねえ、運ちゃん、このバスを運転してどれくらいになるの?」

運転手は帽子の下から暗く見つめ、体を彼らの方へ向けようとしたが、触手はハンドルに張り付いたままだった。前足を勢いよく引いたがそれでも離れないので、バンドルに向かい、 腺から滑る分泌物を絞り出そうと集中しはじめた。粘液の泡がにじみ出てきた。

「早くここから離れよう」とキツネ大が言い、2匹は通りの方へ逃げ出して、ブリクスにぶつかった。

「しょうがない、バスは満席だ」とブリクスが言った。「中がカエルでいっぱいなのがわかっていて、なんで運転手がバスを止めたのかわからないよ」

「あいつは我々にぶつかるところだったんじゃないかと話していたんだ」とキツネ大が言った。「それからドアを開けて予定通りの停車みたいなフリをしたんだ」

「ブリクス、言っておくけど、その可能性についてはっきり声に出して議論したわけじゃなくて、それで正式に同意するチャンスがなかったけど、僕にはまったくありそうなことだと思えるね」とキツネ小が言った。

「バスはみんなあんな風にいっぱいなんじゃないかと思う」とブリクスは唇をかみ、考え、あたりを見回しながら言った。「ただちょっと・・・」。南の方のアパート群を指さした。「しかしたぶん・・・」。ブリクスは空を見上げて星を調べ、頭をかいて、指先で小さくつつく動作で星座を数えた。

「君は僕たちの進路を星を見て決めるつもりなの」とキツネ小が聞いた。

ブリクスは黙って、ペンキ屋の裏のみすぼらしい道を通して北の方に目をこらした。しかし彼らの後を追って副道を行く前に、スモッチキス、私はあなたのためにもう一匹カエルを用意している。 それは何でも載せられる長い睡蓮の葉の上にいる。

 irb> cat = "ブリクス" 
 irb> puts "#{ cat }は何を見てるの?  #{ cat }は気付いているの??" 
   => "ブリクスは何を見てるの?  ブリクスは気付いているの??"

前の小さなカエル(%s%d)は1つの文字列に対するプレースホルダに過ぎなかった。文字列の上で場所取りをするのだ。

こちらの睡蓮の葉はナンバー記号のつぼみで始まる。電話機についているのを見たことがあるだろう。つぼみの後の部分は、2枚の睡蓮の葉っぱで縁取られている。葉っぱは中括弧で、これもコードブロックの蟹のハサミとして前に何度も目にしている。

空の睡蓮の葉っぱ"#{}"は空の文字列""になる。

二重引用符の中に睡蓮の葉っぱがあるときには、Rubyは2枚の葉っぱの間にあるコードを実行する。睡蓮の葉っぱは取り除かれて、かわりにコードの実行結果が置かれる。この睡蓮の葉っぱの置き換えは、式展開と呼ばれている。

 irb> fellows = ['ブリクス', 'キツネ大', 'キツネ小']
 irb> puts "#{ fellows.join 'と' }の旅についていこう。" 
   => "ブリクスとキツネ大とキツネ小の旅についていこう。"

睡蓮の葉っぱは丈夫でどんなコードでも中に入れられる。上の例ではArray#joinを使ったが、何でも好きなものを入れられる。オブジェクトのメソッド呼び出しでも、if文やcase文でも、クラス定義さえ入れることができる。

 irb> blix_went = :北
 irb> puts "ブリクスは黙っていたが、#{ blix_went }の方へ向かい、#{
             if blix_went == :北
               'ペンキ屋の裏のみすぼらしい道を進んだ'
             elsif blix_went == :南
               'アパートの群れへと入っていった'
             else
               '・・・彼がどこへ行ったのか誰も知らない'
             end }。しかし彼らの後を追う前に・・・"
 => "ブリクスは黙っていたが、北の方へ向かい、ペンキ屋の裏のみすぼらしい道を進んだ。
     しかし彼らの後を追う前に・・・"

キツネたちはブリクシーの後について、ペンキ屋の裏を通り、ひび割れてでこぼこのあるアスファルトの道を進んだ。ぼろほろな路地にある店はみんな寄りかかり合って立っていた。ある場所では舗石が地面から突き出し 、道は危なっかしく、 乱雑に連なった岩棚みたいになっていた。まるで都市計画者がプレートテクトニクスを讃えて作ったかのようだ。小さなドラッグストアが地面の下に滑り込んでほとんど見えなくなっていた。

しかしそこは本当にカラフルだった。ペンキ屋が古いペンキを隣近所に投げ出していた。ペンキ屋に最も近い店は、窓枠も雨樋も何百色というペンキが詰まっていた。それに壁や敷石 にも。

基本的にペンキ屋のポーチから始まっているその道は、巨大な不調和の中へと、乏しく染められたマーケットへと続いていた。

さらに進むと、歯医者の建物が赤いペンキに飲み込まれていて、その上に未熟な画家が煙突を通って煤だらけの暖炉に落ちた大きな赤ん坊の絵を描いていた。衝突によって立ち上る灰の煙を描く粗い黒のストロークは、子供の腕と背に生えた濃い毛のように見えた。その子供はたっぷりした髪を 生やすには幼すぎたが、豊かなブロンドの巻き毛が子供の頭から流れ出ていた。子供の足の下には、「ビール飲み」と いう文字が書かれていた。

同じ画家が歯医者の隣の図書館も襲って、足のない赤ん坊のチームが輝く鎖で緑色のスポーツカーをぬかるみの中から引っ張り出している絵を壁いっぱいに手早く描いていた。ここでもまた、すごい金の巻き毛だ!

「答えがほしい」その風景を前に立ち止まってキツネ大が言った。

「そんなものはないんじゃないかという気がし始めたよ」とキツネ小が言った。「ここにあるのが答えなのかも」

「ビール飲みが?」キツネ大が言った。彼は図書館の壁に近づいて、遠近法的に近くにいた足のない子供の1人のほっぺたに触った。その子供の頬にはあご骨が無数にあるように見えた。

ブリクスはさらに2軒先に進んで、歪んだ煉瓦造りの間の舗装された谷間を、R・Kのゴリラ造幣局という金属のステッカーが戸についている建物の所まで来た。その建物にはR・Kのゴリラ造幣局で使えるさまざまな支払いオプションや身分証を表す小さなロゴが貼られていた。窓の格子にさえ、保険情報開示やセキュリティ警告や政府の認可シールが並んでいた。それらすべてに加え、破れたポスターや広告をステッカーが覆い、それをさらにカーボン紙が覆っていた。そしてそのすべてに、どこへでも入り込んでくるペンキの跳ね散らかしが混じり合っていた。

R.K.'s Gorilla Mint.

 

「言ってくれ・・・オレの金は原始的か?? この紙が人間の紙の未開な形態だと思うか? オレの長い指は気味悪いか? ええ??」

「ああ、僕らが入ってきたとき、あんたはそのお金を食べようとしていた」

「新鮮な紙の舌触りが好きなんだ」とカウンターのゴリラが言った。彼の指は札をそっとこすっていた。彼は扇子に拡げた札に顔を近づけ、紙の札の臭いを鼻で嗅いだ。

「今夜はR・Kはいるの?」ブリクスが聞いた。

「R・Kはいない」とゴリラのレジ係が言った。彼は3人の旅行者の方に体を向けて、カウンターの上に金を等間隔に離し、縁をきれいにそろえて並べた。「この中でどれが一番価値が高いと思うね?」

キツネたちは違う種類の札を眺めた。「たぶん——違うな、きっとこれは——待って、バナナが描いたのってある? だって——いや、果物もぶら下がるロープもないや——これは難しいな!」 キツネ小がつぶやいた。そして声を低めて、「難しくてわからない。これは何を表しているんだろう? シンボルか何か? 札にシンボルしか描かれていないなら、どれが一番価値があるか当てるのは僕たちには不可能だ」

「だから推測しなと言ったんだ」ゴリラは札を一枚ずつ順に叩いた。「ほら、確率は5分の1だ」

「シンボルが何か意味しているなら」キツネ大が言った。「当てられるはずだ」

「当てられるとも」とキツネ小が言った。

「いや」とゴリラがいった。「シンボルに意味はない」

「誰が作ったにせよ、お金には意味があるはずだ」とキツネ小が言った。「なぜこのシンボルを使っているのか?」濃いインクで印刷されたアンパサンドを指さした。

「ああ、君がお金の臭いを嗅いで夢想しているところを向こうから見たんだ」とキツネ大が言った。「このシンボルは君にはたくさんの意味があるに違いない!」

「それは違う」とゴリラが言った。

ここで私が口を挟めるのであれば、私はシンボルには意味があると思う。意味がたくさんは詰まってないかもしれないし、割れ目から漏れ出しはしないかもしれないが、一片の意味があるだろうことは 間違いない。

 irb> $:
   => ["/usr/lib/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby/1.8/i686-linux", "/usr/lib/ruby/site_ruby", 
       "/usr/lib/ruby/1.8", "/usr/lib/ruby/1.8/i686-linux", "."]

アメリカのお金の記号で始まる変数はグローバル変数だ。グローバル変数はプログラムのどこからでも、どのスコープの中からでも見える。(ドクター・チャムはこの変数をオリジナルズのコンピュータを探るときに使っていた。)

それではドル記号にコロンが続くのが、requireでファイルをロード するときにRubyが探すディレクトリの配列を表すのはなぜなのだろう?  ドル記号は「グローバル」を意味する。だけどコロンの方は何だ?

歴史的に、多くのオペレーティングシステムでは、ディレクトリのリストはコロンで区切られている。私はこのコロンを、ディレクトリの中でファイルを探すひと組の目だと思うのが好きだ。私たちは目の後に見張るリストを置 いておくのだ。

特別なグローバル変数が他にもいくつかある。

 irb> $"      # $"変数はrequireでロードされたすべてのファイルを保持している。
   => ["irb.rb", "e2mmap.rb", "irb/init.rb", ... "rbconfig.rb"]
              # これらのファイルはどこか別なところに格納されているが、その中のコードはこのプログラム    
              # で使われている。脚注なんかで他の人の仕事を引用するのに似ているので二重引用符       
              # を使う。     

 irb> $0      # $0変数は実行中のプログラムのファイル名を保持している。
   => "irb"   # ゼロは数え上げの最初の数字だと見なせるので、この変数は「このプログラムはどこか
              # ら始まったのか?」と言う質問に答えるのだ。

 irb> $*      # $*変数はプログラムに渡されたすべての引数を保持している。
   => ['--prompt', 'simple']
              # Rubyのメソッドが引数を配列で取るときにアスタリスクを使うことを覚えていれば、これは
              # 簡単に覚えられるだろう。

 # $!は最近発生した例外を保持している。ここでエクスクラメーションは警告状態にあることを示している。例
 # 外だー!
 irb> begin
 irb>   raise TypeError, "この情報はちょっと信じられない。" 
 irb> rescue
 irb>   p $!
 irb> end
   => #<TypeError: この情報はちょっと信じられない。>

 # $@は最近起きた例外のバックトレースを保持している。バックトレースは例外が発生したときにRubyがどこに
 # いたかを示している。
 irb> begin
 irb>   raise TypeError, "この情報はちょっと信じられない。" 
 irb> rescue
 irb>   p $@
 irb> end
   => ["(irb):25:in `irb_binding'", "/usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'", 
       "/usr/lib/ruby/1.8/irb/workspace.rb:52"]

「私は君のことを覚えていない」とブリクスがゴリラのことを興味深そうに見ながら言った。「君はR・Kの子供か何かなのか?」

「ねえったら!」エクスクラメーションマークのついた札をゴリラの鼻先に突き出しながらキツネ小が言った。「これに意味がないなんて言わないで! エクスクラメーションマークが付いているくらいだから、これはきっと重要なのに違いないんだ。もしかしたら緊急の時に使うのかも! 病院の支払いとかそんなときに!」

そうだ、手術だ!」キツネ大が言った。

ゴリラは帽子のつばの下からキツネたちをうんざりしたように見つめた。「いや、違う。手術代にこれを払うことはできない」

「しかし僕たちの話の要点はわかるよね」とキツネ小が言った。彼は他の札を何枚か手に取った。「この札は手術代には使えないと言ったね? それはつまり手術以外の何かの目的があるというふうに聞こえる。じゃあこのクエスチョンマーク のついたやつだ。これは何のため?」

「おい、それを返せ」ゴリラはカウンター越しに札を掴もうとしたが、彼の長い親指が邪魔をして、札を掴んだと思うと、毎回自分の長い親指を掴んでいた。

「おい、おい、こいつ怒ってるぞ」とキツネ大が面白そうに手を叩いた。「何でだろう。我々が興味深い意味について口にしたとたんに彼が怒りはじめたのに気付いた? 当たってるんだ! 我々はゲームをこんなに早く解いてしまったんだ!

「僕たちやったんだ!」キツネ小が言った。彼の一方の肘はゴリラに捕まれていて、もう一方の腕でアンダースコアの書かれた札を振っていた。「これは床関係のものを買うのに使うんだ。タイルとかリノリウムとか」

「わかった」とキツネ大がゴリラの指をほどきながら言った。「あとはどっちが価値が高いか見当をつければいいだけた。手術かリノリウムか! これは簡単だ!」

違う、違うぞ!」ゴリラが叫び、キツネ小を捕まえて平手でぶち始めた。「お前らはサルの金のことを何も分っちゃいない!! お前らは自分たちの金さえ持っていない!!

「自分たちのお金なんて簡単に持つことができるよ!」キツネ大が言い、サルの帽子を取って部屋の向こうに投げた。帽子は飛んでいって貸金庫の裏に落ちた。「君の帽子はあそこだ!」

「ねえ、お札を彼に返しなよ」とブリクスが腕を振りながら言った。「この男は役に立つかもしれないんだ」

「ぶつのやめてったら!」キツネ小が叫んだ。「このドットのあるやつがほとんどわかるところなんだ!!」

突然、警告なしに非常な正確さをもって、キツネ大がサルの鼻を掴んで顔をカウンターに打ち付けた。カウンターの上にあったペンとインク台が震え、キツネ大が「バン!」と言った。 ゴリラの目が眠たげに回り、腕と・・・それから首と・・・そして頭がカウンタ裏の床に滑り落ちた。

あなたが使いたいと思うかもしれないグローバル変数をもういくつか挙げておこう。

 irb> $/      # $/はラインセパレータで、通常は\nがセットされており、これは_Enter_あるいは行末を
   => "\n"    # 表している。スラッシュはファイルの中の行を切る剣だ。

 # ラインセパレータはeach_lineやreadlinesメソッドが文字列をばらばらに分ける仕方を制御する。
 irb> "ジェフ,ジェリー,ジル\nマイケル,メアリー,マートル".each_line { |names| p names }
   => "ジェフ,ジェリー,ジル\n" 
   => "マイケル,メアリー,マートル" 

 # ラインセパレータを変えると、each_lineのようなメソッドの働き方を変える。
 # ラインセパレータをカンマに変えるとどうなるか見てみよう。
 irb> $/ = ','
 irb> "ジェフ,ジェリー,ジル\nマイケル,メアリー,マートル".each_line { |names| p names }
   => "ジェフ," 
   => "ジェリー," 
   => "ジル\nマイケル," 
   => "メアリー," 
   => "マートル" 

 irb> $,     # $,変数はジョイン・セパレータで、Array#joinやKernel::printで文字列をつなぎ合
   => nil    # わせるときに使われる。カンマが接続文字としてよく使われる。

 # ジョイン・セパレータは通常空だ。
 irb> ['ろうそく', 'スープ', 'さば'].join
   => "ろうそくスープさば" 
 irb> $, = ' * '; ['ろうそく', 'スープ', 'さば'].join
   => "ろうそく * スープ * さば" 

 # しかし普通はグローバル変数を変える必要はない。
 irb> ['ろうそく', 'スープ', 'さば'].join ' # '
   => "ろうそく # スープ # さば" 

 irb> $;     # $;変数はスプリット・セパレータで、文字列をString#splitでスプリットするときに使われ
   => nil    # る。

 # スプリットセパレータは通常空になっている。その場合、String#splitは文字列をホワイトスペースのあ
 # るところで分離する。
 irb> "ろうそく  スープ\nさば".split
   => ["ろうそく", "スープ", "さば"]
 irb> $; = ''; "ろうそく  スープ\nさば".split
   => ["ろう", "く スープ\nさば"]

 # しかし、普通はグローバル変数を使う必要はない。
 irb> "ろうそく # スープ # さば".split ' # '
   => ["ろうそく", "スープ", "さば"]

ゴリラ造幣局の外では、ブリクスがキツネたちを叱りつけていた。「あの男の助けを借りることもできたのに! R.K. がどこにいるか彼が知っていれば、彼の情報が利用できたんだ!」

僕たちはサルのお金なんか必要ないよ!」とキツネ小が言った。「僕たちは自分のお金を作れる!

我々は電気リストバンドだって支持する!」とキツネ大が言った。

「彼の金は役立たずだ」とブリクスが言った。「あれはゴリラのお金だ。価値がない。ブルークリスタルよりも悪い」

「しかし何かの目的は持っているはずだ」とキツネ大が言った。

「いや、目的なんてないんだ」とキツネ小が言った。「あいつは単に無価値だと言ってた」

「だけどリノリウムや手術はどうなんだ?」キツネ大が言った。

「ああ、そうだ」キツネ小がブリクスに向かって言った。「リノリウムや手術はどうなの?」

「病院で働いているのがみんなゴリラで、ホームセンターチェーンが厳密にゴリラによって運営されているなら、そう、リノリウムや手術代に使えるろう。しかしすごくずさんなリノリウムと、ぞっとするような手術になるだろうことは請合ってもいい。君たちがあの経済を生き延びられるとは思わないね」

「じゃあ、R・K がそんなに悪賢いなら」キツネ大がずるそうに笑いながら言った。「どうして彼はそんな役立たずな通貨を印刷してるわけ?」

「別な活動を隠蔽するためさ」とブリクス。「それはそうと、君がそんなに賢いなら、どうしてあの哀れなゴリラを乱暴に打ち付けたりしたんだ?」

「あれはいたずらだと思ったんだ」としょげながらキツネ大が言った。「ここにいる友達が、一日中私がどんな極限状態にあったか話してくれるよ」

「そして君の怒りがついに煙を出す鼻を持ち上げたわけだ!」キツネ小が言った。「君はついにそのヤギ髭にふさわしいものになったんだ」

羽のある巻物運搬人

「おい! 私たちを運んでくれ!!」

 

道を進んでいきながら、2匹のキツネにはどこに向かっているのかもわからなかったが、このような緊急時でもあり、ブリクスに先導させながら、今では楽しく時を過ごしていた。彼らはブリクスの後を無頓着に横道にそれながらついていき、通り過ぎる人を邪魔して午後を過ごした。

彼らのそんな実況中継の対象の1つは羽のある巻物の運び屋で、即座に宣誓され、公認される必要のある文書をひと組のコウモリが運んでいた。彼らには遅れることが許されず、素早 さが要求され、巻物を巻く時間さえなく、スイスチーズを放り出してドアから飛び出す必要があった。

この運び屋はRubyでデリミッテドタイプと呼ばれるものを表している。長い一連の文字が巻物を構成し、その両端にはコウモリが配置されて丸まった羽で巻物を支えている。 始めのコウモリは%wと書かれた帽子をかぶっており、これは巻物が言葉(word)の集まりであることを示している。

 irb> bats = %w{The Winged Scroll Carriers}
   => ['The', 'Winged', 'Scroll', 'Carriers']

%w コウモリと巻物をRubyに渡すと、語の配列が出てくる。このシンタックスはそれぞれの語をカンマと引用符で飾るという面倒なことをやりたくない場合のためのショートカットになっている。 あなたはとても急いでいて一刻の猶予もないのだ。それで言葉をコウモリの間に手早くメモし、どこで切ればいいかはRubyに判断させるのだ。

コウモリが違えば帽子も違う。たとえば、%xの帽子は外部プログラムを実行する。

 irb> %w{ruby --help}
   => ["ruby", "--help"]
 irb> %x{ruby --help}
   => "Usage: ruby [switches] [--] [programfile] [arguments] ..."

私のお気に入りは%Qの帽子で、単に%と書くこともできる。これは二重引用符付きの文字列と同じように振る舞うが、何行にも及ぶ 長い文字列を扱うときには見た目が良くなる。たとえばevalで新しいメソッドを追加しようとしているものとしよう。

 m = "bats!" 
 eval %{
   def #{ m }
     puts "|" * 100
   end
 }

二重引用符の文字列と同じように、中で式展開の蓮の葉っぱを使うこともできる。

 Cloneberries: The More You Eat, The More *You*.

 

クローンの実

「食べれば食べるほど、あなたが増えていく!」

ブリクシーは頭を振った。「やれやれ」

「うわっ! 手に子供ができた」小さなキツネの胎児が手の平から出てくるのを見てキツネ大が言った。

「でも、いい実なんだ」とブリクスが言った。「その実で作ったワインを飲むと歯に目玉でできる。それだけさ」

「あっ、痛い!」キツネ小が叫んだ。頭の毛穴からミニチュアの彼が絞り出てきていた。しかしそのすぐ後には、彼は小さな自分を抱えて子守歌を歌っていた。「 またとない、またとない、ナイチンゲールが優しく歌った。瞬く星の光、静かに眠る、スズカケの切り株の上で」

Rubyのオブジェクトを複製するのには、木の実くらいのコードしか必要でない。

 irb> tree = [:berry, :berry, :berry]
   => [:berry, :berry, :berry]
 irb> treechild = tree.clone
   => [:berry, :berry, :berry]

clone メソッドはRubyオブジェクトの正確なコピーを作成する。これは普通の代入とどう違うのだろう?

 irb> tree_charles_william_iii = tree
   => [:berry, :berry, :berry]

変数にオブジェクトを代入するというのはニックネームを新たに作るだけだ。上の配列はいまやtree_charles_william_iii と呼べるようになった。あるいは短くtreeと呼ぶこともできる。同じオブジェクトに違う名前だ。

しかしながら、クローンの方はオブジェクトのコピーだ。コピーは元のオブジェクトに影響を与えることなく変更することができる。

 irb> treechild << 'flower'
   => [:berry, :berry, :berry, 'flower']
 irb> tree
   => [:berry, :berry, :berry]

clone メソッドはオブジェクトに付随するものすべてをコピーするわけではない。上の配列の場合、配列だけがコピーされ、中のシンボルや文字列はコピーされない。

dup メソッドもオブジェクトをコピーするものと思っているかもしれないが、dup メソッドはclone ほど正確にコピーするわけではない。たとえば"frozen"なRubyオブジェクトがあって変更できなかったとする。このオブジェクトをclone すると、その正確なコピーが作られ、コピーもまたfrozenになっている。しかしdupを使った場合にはfrozenでないコピーが作られ、値を変えたければ変えることができる。

cloneメソッドではオブジェクトのメタクラスもコピーされるが、dup の方ではコピーされない。

 irb> o = Object.new
 irb> class << o
 irb>   def nevermore; :nevermore; end
 irb> end

 irb> o.clone.nevermore
   => :nevermore
 irb> o.dup.nevermore
 # NoMethodError: undefined method `nevermore' for #<Object:0xb7d4a484>
 #         from (irb):7

しかしいつもオブジェクトのコピーを作る必要があるわけではない。collectgsubformatといったメソッドの多くは、その仕事の一環としてオブジェクトのコピーを作るからだ。

Deer of the Smoky Pink Puffing.

「ゴホッ」

ピンクの煙を吐くシカ

#####

丘を越え、谷を下り、彼らはピンク色の煙を吐くシカのいる草地に出た。シカの言葉で飾られたピンクの煙が重なり合って太陽はぼんやりとなり、地平はグレープフルーツのグラデーションに染 まり、草地の上に光を宿していた。雲は互いにすれ違い、あるものは上の方へ、カナダにいる親戚の方へと向かい、他のものは受取人の蹄から読める距離に着地した。

「止って! お願い!」キツネ大が叫んだ。「息ができない煙の中に入るつもりはないよ!」

「何を叫んでいるの?」ブリクスが言った。 彼の足の後ろを薄い雲の電報が漂っていた。「囁き以上の大きな声を出す必要はないよ。この長くて薄っぺらな雲は通常ただの呟きかため息だ。最後まで言い終わりさえしていないかもしれない」

「あの雲に書かれているのはみんなシカの言葉なの?」とキツネ小が聞いた。

「助けて! みんなどこにいるんだ?」濃いもうもうとした煙と鋭く薄い雲からなる激しい弁舌に取り巻かれてキツネ大が言った。彼はぐるっと回ってそれぞれの方向に「誰かいたら返事して!」と叫んだ。

彼は濃い雲の中の切れ目を探し、両手でかきながら進んだ。冗長で怒りに満ちた雲は彼を前に突き出し、文の間の短い区切りの中に彼を押し込めることで応えた。彼は くぼみの中に落ち、雲の層が押し寄せてくるのを頭を下げてやり過ごした。

「ああ、シカにはこれが読める」とブリクスが言った。「連中は相手の顔めがけて鼻の穴からこの煙を吹き付けるんだ。僕はシカの恋愛詩に跨った男のことを聞いたことがある」

「バカじゃないの」とキツネ小が言った。

「ああ」とブリクス。「その男というのは僕だ」。ブリクスは腕を伸ばして、頭の上で渦巻いている煙の層につかまった。「どの雲が泣き言で、どの雲が大言壮語か見分けられ さえすればいいんだ」。ブリクスは雲につかまったまま移動し、雲が上向くところで手をゆるめて、足が地面に沿ってゆっくり移動し続けるようにした。「ああ、これはいい方の雲だ。箒の柄 みたいに長い。ちょうど車みたいな形の雲を見つけた男がいるよ。風防に、サイドエアバッグに、パワーステアリング付いている。不思議だよね!」

「そしてその男というのは——」

「僕さ!」そしてブリクスは長い凍った雲に、ぶら下がっている文字を足がかりにしてよじ登り、誇らしげに立って、小さなキツネのとがった影のずっと上の方に浮いていた。

「僕にだってできるよ」とキツネ小が言った。「ノッポと僕はいつもジェットスキーしてるんだ。僕は自分のジェットスキーにちゃんと立ってる。これだって似たようなものさ」

流れてくる煙の間をキツネ大は走り抜けた。文をばらばらにし、文字はごちゃまぜの語になって地面に散らばったが、シカの通信の陰鬱な部分がじめじめした不透明な霧になっている ところで行き詰ってしまった。

一方小さな相棒の方は、細い列になった煙を腕に抱え、滑り降りながら「タリホー!」と叫んだ。しかし彼はあまりにしっかりとつかまっていたため、雲が腕の中で蒸発して下に落っこちた。

あなたはRubyを使い始めたばかりなので、最初は正規表現がよく理解できないかもしれない。Regular Expression Libraryから正規表現を切り取って、その式がどうして機能するのか全然わからないままコードに貼り付けているのかもしれない。 それでうまくいくなら!

 loop do
   print "パスワードを入力してください: " 
   password = gets
   if password.match( /^\w{8,15}$/ )
     break
   else
     puts "** パスワードが間違っています! \
パスワードは8文字から15文字である必要があります!" 
   end
 end

読めないシカ語がこのコード例の中にあるのがわかる? /^\w{8,15)$/ は正規表現だ。翻訳させていただくと、この正規表現は「英字か数字かアンダースコアだけを許容してください。8文字以上、15文字以下で」と言っている。

正規表現はRubyやそのほかのたくさんの言語に組込まれているミニ言語だ。しかしミニと言うべきじゃないかもしれない。正規表現はこんがらがっていて複雑で、Rubyプログラム 自体よりずっと難しいものになりうるからだ。

正規表現の使い方はいたって簡単だ。あのシカのようにやるのだ。難しいのは煙を作るとこだけで、煙に肘を引っかけてマスタードプレッツェルの犬を買いにウィンナーシュニッツェルまでドライブしていくのは簡単なことだ。

 irb> "good_password".match( /^\w{8,15}$/ )
   => #<MatchData:0xb7d54218>
 irb> "this_bad_password_too_long".match( /^\w{8,15}$/ )
   => nil

String#matchメソッドは正規表現を使うもっとも簡単な方法だ。match メソッドは文字列が正規表現で記述されたルールにマッチするかチェックする。正規表現は文字列に対してだけ使えて、一連の条件に文字列が合うか調べる。条件が合えば、MatchData オブジェクトが返される。マッチしなければnilが返される。

文字列の中を検索するというのが最も基本的な正規表現の使い方だ。大きなファイルがあって、その中にある単語やフレーズを探したいとしよう。前から少し時間がたったので、 プリイベンチュアリストの遺失物レジストリを再び検索してみることにしよう。

 require 'preeventualist'
 PreEventualist.searchfound( 'truck' ) do |page|
   page.each_line do |line|
     puts line if line.match( /truck/ )
   end
 end

これは以前に語“truck”を含む行を検索したのとあまり違わない。前はputs line if line['truck']を使ったが、これはただ単語を探す場合に使えるもっと 簡単な方法だ。正規表現/truck/ はこれと等価だ。単語“truck”が文字列のどこかにないか探すのだ。

しかし、大文字になっていたらどうだろう。Truck。そしたらどうする?

 puts line if line.match( /[Tt][Rr][Uu][Cc][Kk]/i )

文字クラスというのは、角カッコで囲まれた区画のことだ。それぞれの文字クラスはその位置でマッチすべき文字のリストを与える。(最初の 文字は大文字のTか小文字のtにマッチする。2番目のはRrにマッチする。以下同様。)

これは以下のようなもっと簡単な書き方ができる:

 puts line if line.match( /truck/i )

正規表現の末尾にある修飾子iは検索するときに大文字小文字を区別しないように 指定している。これはTruckにマッチするTRUCKに もマッチする。TrUcKにもマッチする。そしてそのほかの大文字/小文字を変えたものにもマッチする。

そうだ、あなたのトラックには何かのモデルナンバーがついているかもしれない。T-1000だったかT-2000だったか。よく覚えてない。確かT何千だ。

 puts line if line.match( /T-\d000/ )

このシカ語を見て。\d数字を表す。これは正規表現における数字に対するプレースホルダだ。正規表現はT-1000、 T-2000からT-9000までのどれかにマッチするようになった。

文字クラス
\d 数字にマッチする [0-9]とも書ける
\w 英数字(英字、数字、アンダースコア)にマッチする [A-Za-z0-9_]とも書ける
\s ホワイトスペース(スペース、タブ、CR、LF)にマッチする すなわち[ \t\r\n]
\D 数字以外にマッチする 否定形のセット[^\d]と同じ
\W 英数字以外にマッチする [^\w]と同じ
\S ホワイトスペース以外にマッチする [^\s]と同じ
. ピリオドはすべてにマッチする

正規表現の構築では、これらのプレースホルダをつなぎ合わせ、探すものを表すようにする。1文字の数字にホワイトスペースが続いている所を探すなら、/\d\s/だ。3つの数字が続くのは/\d\d\d/だ。最初のスラッシュと最後のスラッシュは正規表現の始めと終わりを示す。

数字が3つ続くのは/\d{3}/とも書ける。\dのような文字クラスのすぐ後に量指定子を置いて、その文字クラスを何回繰り返すか指定することができる。

量指定子
{n} 正確にn 正確に3つ数字が並ぶのは /\d{3}/
{n,} n 回以上 3文字以上の英字が並ぶのは /[a-z]{3,}/i
{n,n2} n 回以上、n2 回以下 数字かカンマが3から9文字続く場合 /[\d,]{3,9}/
* アスタリスク *{0,} の略記法 コロンの後に0文字以上の英数字が続く場合 /:\w*/
+ プラスは {1,} の略記法 マイナス記号かプラス記号が1文字以上続く /[-+]+/
? クエスチョンマークは {0,1} の略記法 3桁の数字の後にオプショナルなピリオドが続く /\d{3}[.]?/

すごく良く使われる正規表現は、電話番号にマッチするものだ。アメリカの電話番号は(地域コードも含め)数字文字クラスと量指定子でマッチさせることができる。

 irb> "Call 909-375-4434" =~ /\d{3}-\d{3}-\d{4}/
   => 5
 irb> "The number is (909) 375-4434" =~ /[(]\d{3}[)]\s*\d{3}-\d{4}/
   => 14

今回は、式を検索するのにmatch のかわりに=~オペレータを使った。このオペレータはマッチオペレータで、等号記号にチルダがついている。チルダは煙突の縁から出てくる煙りみたいに見える。正規表現みたいな謎の言葉を煙にしてはき出すシカ のイメージで覚えることにしよう。チルダの煙は、正規表現を指し示している。

マッチオペレータは数を返す。この数は、文字列の中で正規表現がマッチした位置を示している。だからマッチオペレータが5を返すなら、「マッチ 部分の前に5文字ある」ということだ。

マッチした文字列全体が必要なら、マッチオペレータを使っている場合には特別なグローバル変数$&で取得できる。match メソッドを使っている場合には、MatchData オブジェクトを文字列に変換すればマッチした文字列が得られる。

 # =~ と $& を使う。
 irb> "The number is (909) 375-4434" =~ /[(]\d{3}[)]\s*\d{3}-\d{4}/
   => 14
 irb> $&
   => "(909) 375-4434" 

 # MatchDataオブジェクトを使う。
 irb> phone = /[(]\d{3}[)]\s*\d{3}-\d{4}/.match("The number is (909) 375-4434")     
   => #<MatchData:0xb7d51680>
 irb> phone.to_s
   => "(909) 375-4434"

ルビイストの多くは、グローバル変数でなくローカル変数のオブジェクトを使う2番目の方法を好んでいる。グローバル変数を使うのは大ざっぱなやり方で、簡単に上書きされてしまうからだ。2つの正規表現を続けて使うなら、グローバル変数は2番目の結果で上書きされる。しかしローカル変数を使うなら、2つのマッチ部分を両方とも保持しておくことができる(別な 変数を使っている限り)。

マッチ以外の正規表現の一般的な使い方として、Rubyで検索置換を行うというのがある。たとえば"cat"という語を探して"banjo"に置き換えることがてきる。 確かにこれは文字列 でも正規表現でもやることができる。

 irb> song = "I swiped your cat / And I stole your cathodes" 
 irb> song.gsub 'cat', 'banjo'
   => "I swiped your banjo / And I stole your banjohodes" 

 irb> song.gsub /\bcat\b/, 'banjo'
   => "I swiped your banjo / And I stole your cathodes"

gsub メソッドは“global substitution” の意味だ。最初の例では“cat”と同時に“cathodes”の最初の3文字も置き換えられているのに注意してほしい。文字列にはシンプルなsub メソッドもあり、これは置換を1回だけ行う。

ブリクスとキツネたちが草地にいる良くしゃべるシカの吐く濃いピンクの煙を進む中、この章は終わる。

 

6. ヤマアラシがどっかに行ってないか確認するために立ち寄っただけ

 The porcupine and his kite again.

 

「帽子が落ちてる」

 

 

7. 出かけています


熱気球で逃げるクウィル。
バンジョーチャンピオンの幕。


バンジョーを傘にしている
クウィル。

ビゲロー(風船を付けたまま行ってしまった犬)に出会った頃のある日、私がガレージセールで買ったボードゲームを引きずってアパートに帰ってくると、クウィルがポーチにいた。彼女は3年くらいというものサンアントニオにいたので、私は驚いた。彼女は私のアパートのポーチで寝袋に入って眠っていた。

彼女は美術学校に行くお金を使い果たしていたので、私のところで5ヶ月かそこら過ごした。

私は中古の2段ベッドを手に入れた。夜にはベッドに座ってお互いにノートに書いた物語りを読み合った。私は探偵少年の本を書いていて、彼は同じテニスチームにいた子供を殺した犯人を、動物たちの助けを借りながら見つける。クウィルは少年が自分の でっちあげたカルトに入る子供を新聞広告で募り、彼らがロケット船を作る ことになるという話を書いていた。しかし彼女の本の大半の部分で子どもたちは森で迷子になっていて、全然方向性がなく、私は毎晩聞いていてスリルを感じた。

そう、毎晩毎晩が、詩と、物語と、近所の人にするいたずらのアイデアだった。近所のジャスティンはWarhammer のファンで、本物の剣とかチュニックとかを集めていた。私たちはアルミホイルで鎧を作り、彼のアパートを 襲撃することにした。私たちは彼のアパートを略奪し、彼はそれが気に入っていた。それで彼も自分の鎧をアルミホイルで作り、みんなでスタジオに行って写真を撮ってもらった。


4人のクウィルがジャッカルの死骸を食べる。

 

私は自分の人生があなたのより少しでもマシだと言うつもりはない。私はただ妹がいないのを寂しく思っているだけだ。今では人生はもうあのときのようではなくなってしまった。私たちは溶解するか なにかしてしまったのだ。

私にはわからない。私は混乱している。これが成長というものなのか? 羽が抜け落ちるのを眺めているのが? そしてその羽が最も愛らしいものだったとしても?

私はそれをすべて止めてしまったのが誰なのか言うのに困難を感じている。誰が誰を愛するのをやめたのか? 私は気にかけるのをやめたのか? あるいは私は彼女を2次元でしか見ておらず、別な角度から見ようとしなかったのかもしれない。私は平面だけ見ていた。そして彼女は私が見ていない間にz軸を上がり、私の方は座標をたどる宿題をしたことがなかった。幾何学的な木の枝と、円の上に居続ける私と。

ブリクスは正しかった。私はこの本を書き続けられる状態にない。これをふるい落とせるまで、お別れだ。

 

「ねえ、戻ってきて!!! 僕たちをここに置いていくつもり??」

「はっ! 僕は正しかったね! 彼はキレたんだ! 彼はすっかり燃え尽きて頭を撃って自殺するんだ!」

「しかし我々はどうなるんだ? あんまり幸先が良くないぞ」
「別に大丈夫だよ。僕たち有名なんだ。他の人が僕たちに似せて描いてくれるよ」

「彼が死んだら僕らは2倍有名になるよ。みんな死んだ人を偶像視するから!」

「待ってよ!」

「彼どこへ行くの??」
「彼がペンを取ったぞ!!」

「それホワイがこの本を書くのに使っていたペンだ!」
「ねえ! 僕らに脚を描いてよ! いいね!」

OK、じゃあ・・・ページを片づけて、Rubyについて見せてあげよう・・・

彼にアライグマの目を描かれたの? 酔っぱらってるみたいだ!!

 

ページをめくる。