ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
AWS Summit
話題の EFS リリースよりも, 以下のブログ記事のサービスアップデートが気になった.
夕飯
- パスタを作る
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (14) ~
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)
定数
以下のコードを実行するとどうなるか.
m = Module.new m.module_eval do EVAL_CONST = 100 end puts "CONST is defined? #{m.const_defined?(:CONST)}" puts "_CONST is defined? #{Object.const_defined?(:CONST)}"
CONST is defined? true CONST is defined? true
以下, irb にて確認.
irb(main):001:0> m = Module.new => #<Module:0x0055719c3d4f88> irb(main):002:0> irb(main):003:0* m.module_eval do irb(main):004:1* CONST = 100 irb(main):005:1> end => 100 irb(main):006:0> irb(main):007:0* puts "CONST is defined? #{m.const_defined?(:CONST)}" EVAL_CONST is defined? true => nil irb(main):008:0> puts "CONST is defined? #{Object.const_defined?(:CONST)}" EVAL_CONST is defined? true => nil
以下, 解説より抜粋.
- 設問において,
module_eval
のブロックで定義した定数はこの問題ではトップレベルで定義したことになる - 定数
EVAL_CONST
はトップレベルで定義していることになる為, Object クラスの定数あることであることを確認出来る Module
クラスのインスタンスには直接, 定数は定義されていないが継承関係を探索して参照することが可能const_defined?
メソッドは第二引数に継承関係を探索するか指定が可能である為, 継承関係を探索するかによって結果は異なる
irb(main):001:0> m = Module.new => #<Module:0x0055f166098fa0> irb(main):002:0> m.module_eval do irb(main):003:1* CONST = 'foo' irb(main):004:1> end => "foo" irb(main):005:0> puts Object.const_defined?(:CONST) true => nil irb(main):006:0> puts m.const_defined?(:CONST) true => nil irb(main):007:0> puts m.const_defined?(:CONST, false) false => nil
ちなみに, 設問において, module_eval
で文字列でメソッドを定義した場合には以下のような挙動になる.
irb(main):001:0> m = Module.new => #<Module:0x0056220dff5138> irb(main):002:0> m.module_eval %Q{ irb(main):003:0" CONST = 'foo' irb(main):004:0" } => "foo" irb(main):005:0> puts Object.const_defined?(:CONST) false => nil irb(main):006:0> puts m.const_defined?(:CONST) true => nil irb(main):007:0> puts m.const_defined?(:CONST, false) true => nil
module_eval
や calss_eval
において, メソッドを文字列で渡すかブロックで渡すかによって定数とクラス変数のスコープは異なるので注意が必要となる. 上記の例だと, 定数は module m 内に定義されていることになる.
ところで, Module.new って出来るんだ...ということで, 以下, ドキュメントより抜粋.
- Module.new
- 名前の付いていないモジュールを新しく生成して返す
- ブロックが与えられると生成したモジュールをブロックに渡し, モジュールのコンテキストでブロックを実行する
mod = Module.new mod.module_eval {|m| ... } mod
また, このメソッドで生成されたモジュールは, 最初に名前が必要になった時に名前が決定する
mod = Module.new mod.module_eval {|m| ... } mod m = Module.new p m # => #<Module 0lx40198a54> p m.name # => nil # まだ名前は未定 Foo = m # m.name # ここで m.name を呼べば m の名前は "Foo" に確定する Bar = m m.name # "Foo" か "Bar" のどちらかに決まる
フムフム.