From: eregontp@... Date: 2021-05-27T15:47:44+00:00 Subject: [ruby-core:104065] [Ruby master Feature#15567] Allow ensure to match specific situations Issue #15567 has been updated by Eregon (Benoit Daloze). What's wrong with this, which works fine? ```ruby def transaction begin puts "Begin Transaction" result = yield success = true result ensure if success puts "Commit Transaction" else puts "Abort Transaction" end end end catch(:ball) do transaction do throw :ball end end ``` IMHO it's clear and explicit. What we want to check here is ultimately if the block was successful (no error of any sort) and the local variable is pretty clear. In fact, you might even want to allow the block to return `:abort` or so, and then it would simply be `if success && result != :abort`. FWIW I think there are very few use cases where `throw`/`catch` are a good idea, but this applies to `break` and others. Short answer: use `ensure` if you want to be sure something runs, `rescue` only captures `Exception`, as expected. ---------------------------------------- Feature #15567: Allow ensure to match specific situations https://bugs.ruby-lang.org/issues/15567#change-92239 * Author: ioquatix (Samuel Williams) * Status: Rejected * Priority: Normal * Assignee: ioquatix (Samuel Williams) ---------------------------------------- There are some situations where `rescue Exception` or `ensure` are not sufficient to correctly, efficiently and easily handle abnormal flow control. Take the following program for example: ``` def doot yield ensure # Did the function run to completion? return "abnormal" if $! end puts doot{throw :foo} puts doot{raise "Boom"} puts doot{"Hello World"} catch(:foo) do puts doot{throw :foo} end ``` Using `rescue Exception` is not sufficient as it is not invoked by `throw`. Using `ensure` is inefficient because it's triggered every time, even though exceptional case might never happen or happen very infrequently. I propose some way to limit the scope of the ensure block: ``` def doot yield ensure when raise, throw return "abnormal" end ``` The scope should be one (or more) of `raise`, `throw`, `return`, `next`, `break`, `redo`, `retry` (everything in `enum ruby_tag_type` except all except for `RUBY_TAG_FATAL`). Additionally, it might be nice to support the inverted pattern, i.e. ``` def doot yield ensure when not return return "abnormal" end ``` Inverted patterns allow user to specify the behaviour without having problems if future scopes are introduced. `return` in this case matches both explicit and implicit. -- https://bugs.ruby-lang.org/ Unsubscribe: