メタプログラミングを1ミリも知らない俺がRubyの魔術に手を染めてみた

タイトルはただのミリしらリスペクトで深い意味はない。

何か新しいことを勉強するときに「○○を1ミリも知らない俺が〜てみた」と脳内でつぶやくとコンテンツ化される(仮説)。Tue Apr 12 04:24:00 via twicli

あ、

勉強会づくりに参考になる素敵資料を紹介します。椅子の並べ方や雰囲気の作り方。AsianPLoP2010で @JoshuaKerievsky が熱く語ってくれた「勉強会パタン言語」 http://bit.ly/ejek6iFri Apr 22 23:15:45 via TweetDeck

わたしも勉強会づくりに参考資料紹介します。手前味噌ですが → リアルイベント開催のためのパターンランゲージ http://j.mp/hVzLLU リアルイベント開催のためのウェブサービス利用のコツ http://j.mp/realeventwebserviceSat Apr 23 06:13:19 via TweetDeck

書こっと

「リアルイベント開催のためのパターンランゲージ」の「3.3 ポジションペーパを用意する」と「3.4 大きな文字の名札」でHamamatsu.rbを思いだし、「3.6 オンラインの感想」を見ての感想を書こっと思った。

Hamamatsu.rb

Hamamatsu.rb静岡県浜松市あたりのRubyなアレです(詳しくはリンク先を)。
第1回キックオフ・ミーティングには僕は参加しなかったのですが、2011年4月13日に開催された第2回に参加しメタプログラミングruby読書会をおこないました。浜松市における『メタプログラミングRuby』在庫状況はたいへんシビアであるなか、僕は前日に一冊だけ発見し無事入手しました。当日は市内すべての『メタプログラミングRuby』が一カ所に集中し、魔術的エネルギが爆発するのではないかと心配でしたが、何も召喚されることはありませんでした。

メタプログラミングRuby

メタプログラミングRuby

勉強会について

KPTによる振り返りが印象的でした。

個人的な観点からもKTPを考えてみます。

  • Keep: 予習をちゃんとした。Wikiに疑問点を記入した。
  • Problem: 初参加にもかかわらず時間ぎりぎりに到着したので、事前にほかの参加者さんと交流できなかった。
  • Try: 早めに会場入りしてあんまり知らないひとと世間話する(話しかけてくださるとうれしいです!)。
    • Challenge: 当日のうちにブログを書く。勉強会中に、新しいひとに興味をもってもらえるような楽しげなツイートをする。

メタプログラミングRuby』について

メタプログラミングは食べたことがないので、おいしいのかどうかもわからず、あまり興味がなかったのですが、勉強会の数時間前に予習をはじめると案外に楽しくて、到着がぎりぎりになってしまいました。

訳が楽しすぎるw #mprubyWed Apr 13 04:58:34 via twicli

「第1章 月曜日: オブジェクトモデル」は、なんとなくわかったふりをしてしまいがちな「オブジェクト」という概念について、またRubyにおける「オブジェクト」について、しっかりと理解させてくれる内容でした。

#mpruby 第1章おもしろいw 概念のパズルみたいで。Wed Apr 13 09:17:07 via twicli

Rubyにおけるオブジェクト、クラス、モジュールなどの関係を図示した57ページ図1-5は刺激的でした。難解な図ではあると思いますが、箱ではなく矢印に注目するとたった二種類の概念しかないことに気づきます。すなわち「クラス−インスタンス関係」と「スーパークラス−サブクラス関係」です。
箱だけをみて、これは「クラス?」、「インスタンス?」、「オブジェクト?」なのかどうか、答えることはできません。ほかの箱との関係をみたときに、やっとその箱が、インスタンスであったり、クラスであったりと判断できます。
というわけで、オブジェクトシステムを理解するためには、「クラス」、「インスタンス」、「オブジェクト」という箱を示す概念を理解するというよりも、その箱のあいだの矢印である「クラス−インスタンス関係」と「スーパークラス−サブクラス関係」という、たった二種類の関係概念を理解することがポイントではないかと思いました。
以下のコードも、そういう関係を意識しながら書いたものです。

謎の断片

Class.new.new が実行できてギョッと思いました。これはどういうことかというと、Class クラスのインスタンス(Class.new)というのは(たとえば String みたいな)いわゆるクラスを意味するものであり、いわゆるクラスがインスタンスを生成(Class.new.new)するのは当たり前ですね。そして、そのインスタンス(たとえば"hoge")はクラスではないので、インスタンスを生成(Class.new.new.new)することはできません。ふつうなら

class Hoge
end

と書いてクラス(Class クラスのインスタンス)を生成するところを Class.new.new とすることで「名前がない謎のクラス」が生成されたということだと思います。

>ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]

>irb
# Class のクラスは Class
irb(main):001:0> Class.class 
=> Class
#「Class のインスタンスx」を生成
irb(main):016:0> c_x = Class.new
=> #<Class:0x27d17f0>
#「Class のインスタンスx」のクラスは Class
irb(main):017:0> c_x.class
=> Class
# 「Class のインスタンスxのインスタンスy」を生成
irb(main):018:0> c_y = c_x.new
=> #<#<Class:0x27d17f0>:0x27cd13c>
# 「Class のインスタンスxのインスタンスy」のクラスは「Class のインスタンスx」
irb(main):019:0> c_y.class
=> #<Class:0x27d17f0>
irb(main):081:0> c_y.class = c_x
=> #<#<Class:0x27c6f80>:0x27c4974>
# 「Class のインスタンスxのインスタンスyのインスタンスz」の生成はできない
irb(main):020:0> c_z = c_y.new
NoMethodError: undefined method 'new' for #<#<Class:0x27d17f0>:0x27cd13c>
        from (irb):20
        from :0
# 「Class のインスタンスxのインスタンスyのクラス」の継承関係
irb(main):024:0> c_y.class.ancestors
=> [#<Class:0x27d17f0>, Object, Kernel]
# ↑すなわち「Class のインスタンスx」というクラスの継承関係
irb(main):056:0> c_x.ancestors
=> [#<Class:0x27d17f0>, Object, Kernel]
# なんかもうよくわからん
irb(main):030:0> Class.class.ancestors
=> [Class, Module, Object, Kernel]
irb(main):031:0> Class.ancestors
=> [Class, Module, Object, Kernel]

# モジュールのクラスは Class(図1-5の補完)
irb(main):006:0> Module.class
=> Class

# 行ったり来たり
irb(main):090:0> Class.new.class
=> Class
irb(main):091:0> Class.new.class.new
=> #<Class:0x2721580>
irb(main):092:0> Class.class.new
=> #<Class:0x2805104>
irb(main):093:0> Class.class.new.class
=> Class
irb(main):097:0> Class.class.class.class
=> Class
irb(main):095:0> "string".class.new
=> ""

Rubyシンタックスハイライトで貼り付けてみましたが、ないよりはましですね。「undefined method `new'」で表示がおかしくなったので「undefined method 'new'」に修正しました。)