ようへいの日々精進XP

よかろうもん

2018 年 06 月 13 日 (水)

ジョギング

  • 自宅→香椎神宮香椎浜
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み... 日に日にひどくなる感じ...
  • ストレッチでごまかす

日課

  • 休み

fukuoka.rb

fukuokarb.connpass.com

に参加した.

以下の 2 つのプルリクエストをこさえた.

github.com

github.com

今日のるびぃ ~ REx - Ruby Examination にチャレンジ (26) ~

REx - Ruby Examination の問題を自分なりにアレンジした上で 1 〜 3 問くらいずつ解いていく. 正直言ってかなり難しい. 尚, irb に動作確認環境は以下の通り.

$ ruby --version
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]
$ irb --version
irb 0.9.6(09/06/30)

引き続き, class_eval による定数参照

以下のコードは Hello, world を表示する. 同じ結果となるコードを複数選択する.

module M
  CONST = "Hello, world"

  class C
    def awesome_method
      CONST
    end
  end
end

p M::C.new.awesome_method

以下, 解答.

# 解答(1)
class C
end

module M
  CONST = "Hello, world"

  C.class_eval do
    def awesome_method
      CONST
    end
  end
end

p C.new.awesome_method

# 解答 (2)
class C
  CONST = "Hello, world"
end

module M
  C.class_eval(<<-CODE)
    def awesome_method
      CONST
    end
  CODE
end

p C.new.awesome_method

以下, irb にて確認.

# 設問コード
irb(main):001:0> module M
irb(main):002:1>   CONST = "Hello, world"
irb(main):003:1> 
irb(main):004:1*   class C
irb(main):005:2>     def awesome_method
irb(main):006:3>       CONST
irb(main):007:3>     end
irb(main):008:2>   end
irb(main):009:1> end
=> :awesome_method
irb(main):010:0> 
irb(main):011:0* p M::C.new.awesome_method
"Hello, world"
=> "Hello, world"

# 解答(1)
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   CONST = "Hello, world"
irb(main):006:1> 
irb(main):007:1*   C.class_eval do
irb(main):008:2*     def awesome_method
irb(main):009:3>       CONST
irb(main):010:3>     end
irb(main):011:2>   end
irb(main):012:1> end
=> :awesome_method
irb(main):013:0> 
irb(main):014:0* p C.new.awesome_method
"Hello, world"
=> "Hello, world"


# 解答(2)
irb(main):001:0> class C
irb(main):002:1>   CONST = "Hello, world"
irb(main):003:1> end
=> "Hello, world"
irb(main):004:0> 
irb(main):005:0* module M
irb(main):006:1>   C.class_eval(<<-CODE)
irb(main):007:2"     def awesome_method
irb(main):008:2"       CONST
irb(main):009:2"     end
irb(main):010:2"   CODE
irb(main):011:1> end
=> :awesome_method
irb(main):012:0> 
irb(main):013:0* p C.new.awesome_method
"Hello, world"
=> "Hello, world"

以下, 解説より抜粋.

  • 解答 (1)
    • class_eval にブロックを渡した場合は, ブロック内のネストはモジュール M になる
    • そのコンテキストから定数を探索するので "Hello, world" が表示される
  • 解答 (2)
    • class_eval に文字列を渡した場合のネストの状態はクラス C となる
    • CONST はクラス C にある為, "Hello, world" が表示される

念の為, ブロックで渡した場合と, 文字列で渡した場合のネストの状態を確認してみる.

# class_eval のブロック渡し
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   C.class_eval do
irb(main):006:2*     Module.nesting
irb(main):007:2>   end
irb(main):008:1> end
=> [M]
irb(main):009:0> exit

# class_eval の文字列渡し
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   C.class_eval(<<-CODE)
irb(main):006:2"     Module.nesting
irb(main):007:2"   CODE
irb(main):008:1> end
=> [C, M]

上記のように, ネストの状態が異なる為, 定数を探索するコンテキストも異なることが解る.

フムフム.