Exceptions: why does adding brackets change anything?

There are a few things I would like to understand in how Ruby handles inline error handlers.

Case 1

This is a common use case.

def foo raise Error end bar = foo rescue 1 # => 1 bar # => 1 

It works as expected. The expression foo rescue 1 returns 1 and is correctly assigned to bar .

Case 2

Ruby allows you to process arrays, so this behavior seems odd.

 baz = 'a' baz, bar = foo rescue [1, 2] # => [1, 2] baz # => 'a' bar # => nil 

The expression returns an array [1, 2] , but does not deconstruct or assign it. He completely misses the task at all.

Case 3

However, when you complete the error in brackets, deconstruction works.

 baz, bar = (foo rescue [1, 2]) # => [1, 2] baz # => 1 bar # => 2 

Case 4

Bonus points: increasing the error and trying to process it inline also misses the assignment

 baz = raise Error rescue 1 # => 1 baz # => nil 

But adding brackets makes it work.

Edit

I tested this on Ruby 1.9.3-p392 and Ruby 2.0.0

Edit 2 :

I added tags to cases

Edit 3 :

Apparently, some people think that this is not a question, so perhaps the name was not obvious enough. Here is the question in the full text:

Why do these inconsistencies arise and why does adding brackets change something?

+6
source share
2 answers

Your case 2 is the same:

 baz = 'a' (baz, bar = foo) rescue [1, 2] 

Since foo causes an error, assigning the values baz and bar fails, so baz remains "a" and bar remains nil , the value that was assigned during the parsing stage. Then the assignment receives salvation, and the return value will be [1, 2] .

Your case 4 is the same:

 (baz = raise Error) rescue 1 

Since the right side of the assignment causes an error, the assignment of baz fails, and baz will remain nil , which was assigned at the parsing stage. Then the assignment is assigned, and the return value is 1 .

+1
source

Update: Sorry, my example did not work. I think this is a mistake in the parser, since simple assignment does not suffer from this problem.

 bar, baz = 1,2 # bar == 1, baz == 2 bar = foo rescue [3,4] # bar == [3,4], baz == 2 bar, baz = 1,2 # bar == 1, baz == 2 bar, baz = foo rescue [3,4] # no assignment done: bar == 1, baz == 2 

Even the priority of salvation cannot explain why simple assignment is performed, but multi- not.

+1
source

All Articles