メタプログラミングRuby 4章のブロックに関してのアウトプット。
変数のscopeを越える方法(スコープゲートの突破)をまとめます。
Before
scope.rb
var = "scopeを越える瞬間!!"
puts var #=> scopeを越える瞬間!!
class HogeClass# スコープの壁①
puts "①ここで使えるようにしたい"
puts var #=> error
def magic_scope# スコープの壁②
puts "②メソッドの中でも使いたい"
puts var
end
end
実行すると....
$ ruby scope.rb
scopeを越える瞬間
ここで使えるようにしたい
scope.rb:11:in `<class:HogeClass>': undefined local variable or method `var' for HogeClass:Class (NameError)
Did you mean? var
from scope.rb:8:in `<main>'
→ 普通にscopeで落ちる。
これを使えるようにしてしまうのが、スコープのフラット化 というものです。
After
まずは①のスコープゲートを超える方法。
classをスコープゲートではない、メソッド呼び出しに置き換える。メソッド呼び出し。
→ブロックをClass.newに渡すと、クラスにインスタンスメソッドを定義することができます。
scope.rb
var = "scopeを越える瞬間"
puts var
HogeClass = Class.new do # ブロックをClass.newに渡す
puts "ここで使えるようにしたい"
puts "①:#{var}" # ①
def magic_scope
puts "メソッドの中でも使いたい"
puts "②:#{var}" # ②
end
end
実行
$ ruby scope.rb
scopeを越える瞬間
ここで使えるようにしたい
①:scopeを越える瞬間 #=> 超えた!!
続いて②を超えます。
ここもメソッド呼び出しに置き換えることで実現可能。
define_methodを使用する。
scope.rb
var = "scopeを越える瞬間"
puts var
HogeClass = Class.new do
puts "ここで使えるようにしたい"
puts "①:#{var}"
define_method(:magic_scope) do
puts "メソッドの中でも使いたい"
puts "②:#{var}"
end
end
puts HogeClass.new.magic_scope
実行
$ ruby scope.rb
scopeを越える瞬間
ここで使えるようにしたい
①:scopeを越える瞬間
メソッドの中でも使いたい
②:scopeを越える瞬間
以上です。
フラットスコープを駆使すれば、スコープでやりたいことはほとんどできそうです
個人開発の時にはどんどん使用してみます。