From: samuel@... Date: 2019-01-29T21:21:33+00:00 Subject: [ruby-core:91322] [Ruby trunk Feature#15567] Allow ensure to match specific situations Issue #15567 has been updated by ioquatix (Samuel Williams). So, @jeremyevans0, I agree with everything you say. That being said, this proposal goes beyond just that single case. For example, there is no easy way to capture `retry` or `redo` exiting a block. Looking at your example, e.g. ```ruby def doot ret = yield normal_exit = true ret ensure # Did the block return normally return "abnormal" if $! || !normal_exit end ``` I certainly prefer ```ruby def doot yield ensure when not return return "abnormal" end ``` It's clearer what's going on (especially if function is more complex than 1 line of actual code), it should be more efficiently implemented by VM since it only affects non-normal flow control and there is no conditional checks required. ---------------------------------------- Feature #15567: Allow ensure to match specific situations https://bugs.ruby-lang.org/issues/15567#change-76572 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal * Assignee: ioquatix (Samuel Williams) * Target version: ---------------------------------------- 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: