Issue #15567 has been updated by shevegen (Robert A. Heiler).


I was about to write a long comment, but then I noticed that my reply would be too long, so I shortened
this. So just a few key statements:

- I don't like the proposed syntax suggestion here in particular:

    ensure when not return

The reason why I dislike it is partially due to the syntax verbosity; but also because, more significantly,
because it appears to do conditional checks in very different means than have existed before in ruby.
I would expect "when" usually in a case-structure.

There was this other recent suggestion to also add "when", to allow for chaining after the addition of
the alias "then" to "yield_self", leading to chains of .when .then .when .then; and I also am not a huge fan
of using "when" that way. Of course there is more than one way to do something, but my own personal
preference would be to keep "when" reserved for case-when layouts.

As for catch/throw: I think it is a lot more common to see begin/rescue than catch/throw. Even if this
may be slower (e. g. some people doing control flow logic with begin/rescue), I think the intent and
clarity of intent is much clearer with control flows based on begin/rescue (and ensure) style layout
of code. So to conclude and finish my comment, I think it would be better to not introduce a more
complicated ensure conditional clause as proposed in the suggestion here. IMO you can re-structure
your code to keep ensure simple, so it should not be necessary to add additional conditionals into
ensure, even more so when these are unusual in regards to syntax - it would be the first time that I
would see "ensure when" and I don't quite like that syntax suggestion in this context.

----------------------------------------
Feature #15567: Allow ensure to match specific situations
https://bugs.ruby-lang.org/issues/15567#change-76531

* 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: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>