[#104307] Float truncate — Eustáquio Rangel <eustaquiorangel@...>
Hi!
4 messages
2021/06/16
[ruby-core:104144] [Ruby master Feature#15567] Allow ensure to match specific situations
From:
eregontp@...
Date:
2021-06-02 11:34:28 UTC
List:
ruby-core #104144
Issue #15567 has been updated by Eregon (Benoit Daloze).
> I suspect that there is existing buggy code which has ensure blocks and checks $! which fails in the case I mentioned.
Typically that's an anti-pattern.
In 99% cases, the ensure code should do its logic regardless whether there is an ongoing exception/unwind or not.
Seems Jeremy agrees in comment 7:
> I think we should definitely not add syntax in an attempt to make it easier to treat a non-local, non-exception exit differently than a normal exit, as doing so is usually a mistake.
---
> Eregon (Benoit Daloze) throw should not abort the transaction, it should be committed.
That is surprising to me.
If `throw` is performed in the middle of the transaction block then maybe only half the operations are done, committing in that case seems wrong.
```ruby
transaction do
update1
some_call_that_ends_up_in_throw
update2
end
```
----------------------------------------
Feature #15567: Allow ensure to match specific situations
https://bugs.ruby-lang.org/issues/15567#change-92315
* 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: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>