Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exceptions: why does adding parenthesis change anything?

Tags:

exception

ruby

There are a few things I'd like to understand in how Ruby treats 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 it is correctly assigned to bar.

Case 2

Ruby allows descructuring arrays, so this behavior seems odd.

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

The expression returns the array [1, 2] but doesn't deconstruct or assign it. It completely skips the assignment altogether.

Case 3

When you wrap the the error in parenthesis, however, the deconstruction works.

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

Case 4

Bonus points: Raising the Error and trying to handle it inline also skips assignment

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

But adding parenthesis makes it work.

Edit:

I tested this on Ruby 1.9.3-p392 and Ruby 2.0.0

Edit 2:

I added labels to cases

Edit 3:

Apparently some folks think this isn't a question, so maybe the title wasn't obvious enough. Here's the question in full text:

Why do these inconsistencies happen, and why does adding parenthesis change anything?

like image 545
gmalette Avatar asked Apr 08 '13 13:04

gmalette


1 Answers

Your case 2 is the same as this:

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

Since foo raises an error, assignment of values to baz and bar fails, so baz remains to be "a", and bar remains to be nil, a value that was assigned during the parsing stage. Then, the assignment gets rescued, and the return value would be [1, 2].

Your case 4 is the same as this:

(baz = raise Error) rescue 1

Since the righthand side of the assignment raises an error, assignment to baz fails, and baz would remain to be nil, that was assigned during the parsing stage. Then, the assignment is rescued, and the return value is 1.

like image 177
sawa Avatar answered Nov 03 '22 20:11

sawa