ようへいの日々精進XP

よかろうもん

2018 年 07 月 03 日 (火)

ジョギング

  • 台風接近の為, お休み

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

サッカーワールドカップ

  • 日本対ベルギー
  • 深夜 3 時ということでリアルタイムでは観戦せず
  • 朝起きてから結果を見て残念だったけど, 試合内容に感動して勇気づけられた

台風接近

  • 朝から雨が降ったりやんだり
  • 夕方から風が強くなって, いまでも風雨が強い

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

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)

const_defined?

以下のコードを実行するとどうなるか.

mod = Module.new

mod.module_eval do
  EVAL_CONST = 100
end

puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST)}"
puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST)}"

以下, 解答.

EVAL_CONST is defined? true
EVAL_CONST is defined? true

と出力される. 以下, irb による確認.

irb(main):001:0> mod = Module.new
=> #<Module:0x0055a82e4d0d88>
irb(main):002:0> 
irb(main):003:0* mod.module_eval do
irb(main):004:1*   EVAL_CONST = 100
irb(main):005:1> end
=> 100
irb(main):006:0> 
irb(main):007:0* puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST)}"
EVAL_CONST is defined? true
=> nil
irb(main):008:0> puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST)}"
EVAL_CONST is defined? true
=> nil

以下, 解説より抜粋.

  • 設問の module_eval では, ブロックで定義されている為, 定数はトップレベルで定義されることになる
  • トップレベルの定数 = Object クラスの定数となる為, mod.const_defined?Object.const_defined?true を返す
  • const_defined? は, 第 2 引数に継承関係を探索するか指定出来る為, 引数の有無によって結果が異なる

以下のような場合にどうなるか.

mod = Module.new

mod.module_eval %Q{
  EVAL_CONST = 100
}

puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST)}"
puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST)}"

以下のように出力されると想定.

EVAL_CONST is defined? true
EVAL_CONST is defined? false

以下, irb による確認.

irb(main):001:0> mod = Module.new
=> #<Module:0x0055d0e10d4f00>
irb(main):002:0> 
irb(main):003:0* mod.module_eval %Q{
irb(main):004:0"   EVAL_CONST = 100
irb(main):005:0" }
=> 100
irb(main):006:0> 
irb(main):007:0* puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST)}"
EVAL_CONST is defined? true
=> nil
irb(main):008:0> puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST)}"
EVAL_CONST is defined? false
=> nil

module_eval でメソッドを定義する場合, 文字列で定義する場合とブロックで定義するでネストの状態が異なる為, 定数の参照スコープも異なる. 上記の例では, 文字列で定義されている為, 定数の参照は mod インスタンス内に制限されていることが判る.

alias

以下の実行結果になるように __(1)__ に当てはまるコードを選ぶ.

class String
  __(1)__
end

p '12345'.foo

# 実行結果
54321

以下, 解答.

alias foo reverse
alias :foo :reverse

以下, irb による確認.

irb(main):001:0> class String
irb(main):002:1>   alias foo reverse
irb(main):003:1> end
=> nil
irb(main):004:0> 
irb(main):005:0* p '12345'.foo
"54321"
=> "54321"
irb(main):006:0> exit
kappa@tpX1-Carbon:~/sandbox/ruby-exam-gold$ irb
irb(main):001:0> class String
irb(main):002:1>   alias :foo :reverse
irb(main):003:1> end
=> nil
irb(main):004:0> 
irb(main):005:0* p '12345'.foo
"54321"
=> "54321"

以下, 解説より抜粋.

alias new_method old_method
alias :new_method :old_method
alias $new_global_val $old_global_val
  • alias_method でもメソッドに別名を付けることが出来る
  • alias との違いは, メソッド名は String か Symbol で指定する, また, グローバル変数の別名を付けることは出来ない
irb(main):006:0> module Kernel
irb(main):007:1>   alias_method :foo, :puts
irb(main):008:1> end
=> Kernel
irb(main):009:0> foo 'foo'
foo
=> nil

フムフム.