[ruby-list:50910] Re: 一時的にグローバル変数を差し替える

From: dogatana <dogatana@...>
Date: 2020-10-04 00:43:56 UTC
List: ruby-list #50910
こんにちは、市田です。

どこまで汎用的にするかによりますが、メタプログラミング Ruby 第2版4.2.1 using キーワード
にある with と置き換え用クラスを使うと、利用箇所そのものはコンパクトになります。

module Kernel
  def with(replacer)
    yield
  ensure
    replacer.restore
  end
end

class Replacer
  def initialize(sim, new_value)
    @sim = sim
    replace(new_value)
  end

  def restore
    global_variable_set(@sim, @old_value)
  end

  private

  def replace(new_value)
    @old_value = global_variable_get(@sim)
    global_variable_set(@sim, new_value)
  end

  def global_variable_get(sim)
    eval "#{sim}"
  end

  def global_variable_set(sim, value)
    eval "#{sim} = value"
  end
end

$val = 1
puts $val
with Replacer.new(:$val, 3) do
  puts $val
end
puts $val

File.open('temp.txt', 'w') do |f|
  $stdout.puts 'before with'
  with (Replacer.new(:$stdout, f)) do
    $stdout.puts 'in with'
  end
  $stdout.puts 'after with'
end

In This Thread