From: nobu@... Date: 2017-09-24T12:59:43+00:00 Subject: [ruby-core:82952] [Ruby trunk Feature#13923] Idiom to release resources safely, with less indentations Issue #13923 has been updated by nobu (Nobuyoshi Nakada). How about: ```ruby class Deferred def initialize @list = [] yield self ensure @list.reverse_each do |res, clean| clean.(res) end end def defer(res = true, &clean) @list << [res, clean||CLOSE] if res res end CLOSE = :close.to_proc end if $0 == __FILE__ class Resource @@number = 0 def initialize @num = @@number += 1 end def close puts "#@num closed" end def delete puts "#@num deleted" end end Deferred.new do |d| r0 = Resource.new d.defer {r0&.close} r1 = Resource.new d.defer r1 r2 = d.defer Resource.new abort unless Resource === r2 r3 = d.defer(Resource.new) {|r|r.delete} end end ``` ---------------------------------------- Feature #13923: Idiom to release resources safely, with less indentations https://bugs.ruby-lang.org/issues/13923#change-66855 * Author: tagomoris (Satoshi TAGOMORI) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- In programs which grabs and releases resources very often, we need to write so much begin-ensure clauses. ```ruby begin storage = getStorage() begin buffer = storage.get(buffer_id) # ... ensure buffer.close if buffer end rescue StorageError => e # ... ensure storage.close if storage end ``` Such code makes our code fat, and difficult to understand. I want to write such code like below: ```ruby # Class of storage and buffer should include a module (like Closeable) # or be checked with respond_to?(:close) begin(storage = getStorage(); buffer = storage.get(buffer_id) # ... rescue StorageError => e # ... end # (buffer.close if buffer) rescue nil # (storage.close if storage) rescue nil ``` Other languages also have similar features: * Java: try-with-resources * Python: with -- https://bugs.ruby-lang.org/ Unsubscribe: