Rubyは、リテラルの匿名プロシージャ(Rubyではブロックと呼ばれます)を構文的に軽量にサポートしています。したがって、このための新しい言語機能は必要ありません。
したがって、通常行うことは、コードのブロックを取得し、リソースを割り当て、そのリソースのコンテキストでコードのブロックを実行してから、リソースを閉じるメソッドを作成することです。
このようなもの:
def with(klass, *args)
yield r = klass.open(*args)
ensure
r.close
end
あなたはそれをこのように使うことができます:
with File, 'temp.txt', 'w' do |f|
f.write 'hi'
raise 'spitespite'
end
ただし、これはこれを行うための非常に手続き的な方法です。Rubyはオブジェクト指向言語です。つまり、aのコンテキストでコードのブロックを適切に実行する責任は、次のクラスFile
に属する必要があります。File
File.open 'temp.txt', 'w' do |f|
f.write 'hi'
raise 'spitespite'
end
これは、次のように実装できます。
def File.open(*args)
f = new(*args)
return f unless block_given?
yield f
ensure
f.close if block_given?
end
これは、Rubyコアライブラリ、標準ライブラリ、およびサードパーティライブラリの多くのクラスによって実装される一般的なパターンです。
一般的なPythonコンテキストマネージャープロトコルとのより密接な対応は次のとおりです。
def with(ctx)
yield ctx.setup
ensure
ctx.teardown
end
class File
def setup; self end
alias_method :teardown, :close
end
with File.open('temp.txt', 'w') do |f|
f.write 'hi'
raise 'spitespite'
end
これはPythonの例と実質的に区別がつかないことに注意してください。ただし、言語に新しい構文を追加する必要はありませんでした。