『メタプログラミングRuby』の第3章まで読み終えました。まだ途中ですが,いろいろと刺激を与えてくれる本で,難しいところもありますが,わくわくドキドキしながら読み進めています。
第3章の最後に紹介されている,blocks/monitor_final/redflag.rb なんかは,じっくり考えると納得できますが,果たして自分がこんな風に書けるようになるんだろうかとも思います。
第3章の復習を兼ねて,以下を作ってみました。実行結果を予測できますか?
chap3_test.rb
#!/usr/bin/env ruby ######################### # (1) lambda { @str = "Hello, Ruby(1)" def hello1 puts @str end }.call hello1 ######################### # (2) lambda { str = "Hello, Ruby(2)" Kernel.send :define_method, :hello2 do puts str end }.call hello2 ######################### # (3) lambda { str = "Hello, Ruby(3)" def hello3 puts str end }.call hello3
解説?
(1)は,トップレベルのインスタンス変数@strを使ってます。mainがselfになる場所であればどこからでも呼び出せるので実行できます(p114参照)。
(2)は,strはローカル変数ですが,Module#define_methodを使うことで,スコープゲートを超えて,strをhello2に渡すことができるので実行できます(p116参照)。
(3)は,strはローカル変数で,hello3からのスコープを外れて見えなくなるため実行できません。一見,hello3から外側のstrは見えるような気がしますが,Rubyにはこうした可視性の入れ子構造は存在せず,スコープはきちんと区別されているそうです(p113参照)。