if statements do not introduce scope in Ruby 1.9, what is the rationale behind this change from ruby 1.8?
Two reasons why this was done in Ruby 1.9 are on the following slides, although it may not be obvious without the presenter's dialog. Two things that the no scope
if statements allow you to do is to define things in your source code that can be accessed outside the if statement.
First example: Replace methods
class Employee if String.method_defined?(:encode) def name ... end else def name ... end end end
In this example, there are two different definitions for the
name method. One that will be used if the
String.encode method exists, and one (inferior implementation) that will be used if the encode method doesn't exist. Essentially, this allows you to use a correctly encoded string if the libraries support it.
Second example: Replace implementation
if String.method_defined?(:encode) module Builder ... end else class String ... end end
In this example, we are providing a completely different class/module depending on if a library feature exists. This allows you to have a completely different algorithm that uses a new library feature while still falling back to a less efficient or complete algorithm that is close enough if it doesn't exist.
The all important why
So what does this buy you? If the
if statement introduced a new scope, the new method or class would only exist and be used within the confines of the
if statement. That constraint makes it very hard to support a library that will need changes for Ruby 2.0 as we migrate away from 1.9 in the future.
With both the examples provided in the presentation you linked to, the reasoning is to maintain one codebase for your libraries while still supporting multiple versions of Ruby. I believe it was born out of the pain of transitioning between Ruby 1.8 and Ruby 1.9. As the Ruby team is steadily marching towards 2.0, you will still be able to support your users when there are incompatible changes. I believe there were some between 1.9.1 and 1.9.2. There will be more in the future.
I'm no expert, but if you take a look at the Ruby FAQ here: http://arc.apotheon.org/ruby/faq/rubyfaq-2.php
Section 2.3 "When does a local variable become accessible?" shows the current behaviour.
To get around the scoping issue, one of the slightly "hacky" things that you currently have to do is:
You are recommended to put an assignment statement like a = nil before accessing a local variable not to be bothered by such behaviour of local variables.
I believe that 1.9 will remove the need to do this, and this might be one of the drivers for the new behaviour.