Ruby
メタプログラミング
スコープ

メタプログラミングRuby 4章 スコープを越える スコープゲート フラットスコープ その1

More than 1 year has passed since last update.

メタプログラミング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を越える瞬間

以上です。
フラットスコープを駆使すれば、スコープでやりたいことはほとんどできそうです
個人開発の時にはどんどん使用してみます。