From: josh.cheek@... Date: 2016-11-07T03:19:03+00:00 Subject: [ruby-core:78027] [Ruby trunk Feature#12906] do/end blocks work with ensure/rescue/else Issue #12906 has been updated by Josh Cheek. My error on the duplication, I tried searching a couple different ways but the first results weren't about this and I didn't see how to use the filters and the keywords together. Fortunately it seems congruent with https://bugs.ruby-lang.org/issues/7882 Shyouhei Urabe wrote: > So from the patch you sent, I guess you are implicitly proposing to forget about `{...}`-style blocks for a while and focus on `do ... end`-style blocks. That is in fact a wise idea. To start small is a wisdom we learned in this forum. Ty :) the existing places it works are begin/end, def/end, class/end, so it felt unifying to add do/end, but seemed less natural with curly braces. I'm sure I'd get used to it, if it were there, though. ---------------------------------------- Feature #12906: do/end blocks work with ensure/rescue/else https://bugs.ruby-lang.org/issues/12906#change-61376 * Author: Josh Cheek * Status: Assigned * Priority: Normal * Assignee: Yukihiro Matsumoto ---------------------------------------- When you want to rescue in a block, you must do this: ~~~ruby lambda do begin raise 'err' rescue $! # => # end end.call ~~~ I've wished on numerous occasions that I could omit the begin/end and not need the extra wrapper: ~~~ruby lambda do raise 'err' rescue $! # => # end.call ~~~ This would be consistent with how classes and methods work: ~~~ruby class C raise 'err' rescue $! # => # end send def m raise 'err' rescue $! # => # end ~~~ It's not really clear to me how to submit this since it may require some discussion, but this is the diff: ~~~diff diff --git a/parse.y b/parse.y index 54ccc52..223e5d3 100644 --- a/parse.y +++ b/parse.y @@ -3757,7 +3757,7 @@ brace_body : {$$ = dyna_push();} do_body : {$$ = dyna_push();} {$$ = cmdarg_stack >> 1; CMDARG_SET(0);} - opt_block_param compstmt + opt_block_param bodystmt { $$ = new_do_body($3, $4); dyna_pop($1); ~~~ I added tests for ensure to rubyspec, but there wasn't an obvious place to talk about rescue/else in this context (the spec for rescue only uses it in a begin/end block) It's probably fine as the spec for ensure does hit rescue, too, and they ultimately delegate to the same pieces. Not totally clear, though. I can do more with that if you need. ~~~diff diff --git a/language/ensure_spec.rb b/language/ensure_spec.rb index 13575fc..b14b0b5 100644 --- a/language/ensure_spec.rb +++ b/language/ensure_spec.rb @@ -124,3 +124,74 @@ describe "An ensure block inside a method" do @obj.explicit_return_in_method_with_ensure.should == :ensure end end + +describe "An ensure block inside a do block" do + before :each do + ScratchPad.record [] + end + + it "is executed when an exception is raised in it's corresponding do block" do + begin + lambda do + ScratchPad << :begin + raise "An exception occured!" + ensure + ScratchPad << :ensure + end.should raise_error(RuntimeError) + + ScratchPad.recorded.should == [:begin, :ensure] + end + end + + it "is executed when an exception is raised and rescued in it's corresponding do block" do + begin + lambda do + ScratchPad << :begin + raise "An exception occured!" + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end.call + + ScratchPad.recorded.should == [:begin, :rescue, :ensure] + end + end + + it "is executed even when a symbol is thrown in it's corresponding do block" do + begin + catch(:symbol) do + lambda do + ScratchPad << :begin + throw(:symbol) + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end.call + end + + ScratchPad.recorded.should == [:begin, :ensure] + end + end + + it "is executed when nothing is raised or thrown in it's corresponding do block" do + lambda do + ScratchPad << :begin + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end.call + + ScratchPad.recorded.should == [:begin, :ensure] + end + + it "has no return value" do + lambda do + :begin + ensure + :ensure + end.call.should == :begin + end +end ~~~ -- https://bugs.ruby-lang.org/ Unsubscribe: