Ruby Gotchas 1 – return in ensure

The difference between Ruby's implicit “value of a block” and its explicit “return from a method with a value” is best illustrated by example.

def foo
	puts 'a'
	0
ensure
	puts 'b'
	1
end

irb(main):001:0> foo
a
b
=> 0

def bar
	puts 'a'
	return 0
ensure
	puts 'b'
	return 1
end

irb(main):002:0> bar
a
b
=> 1

The explicit return statement literally means “stop the method right now, and use this return value”, whereas in uninterrupted flow the ensure sub-block's final value is superseded by the method's.

The gotcha happens thus:

def baz
	puts 'a'
	raise 'fail'
ensure
	puts 'b'
	1
end

irb(main):003:0> baz
a
b
RuntimeError: fail
	from (irb):19:in `baz'
	from (irb):34
	from /usr/bin/irb1.9.1:12:in `<main>'

def freb
	puts 'a'
	raise 'fail'
ensure
	puts 'b'
	return 1
end

irb(main):004:0> freb
a
b
=> 1

The same thing happened in Ruby 1.8 – it's a language feature. This is partly why I don't use return statements, except when I really want to be explicit about breaking the flow.


Matthew Kerwin

Published
Modified
License
CC BY-SA 4.0
Tags
development, gotcha, ruby, software

Comments powered by Disqus