Ruby warnings and scope

Today I wrote some Ruby code at work. We use Ruby 1.8 for reasons I won’t go into here. The code works fine, no issues. But we use Rubocop (under Ruby 1.9) to enforce consistent styles and also to look for any kind of oddity situations that might bite us.

Today Rubocop complained at me about my code. Likewise, many versions of Ruby complained in the same manner, excluding Ruby 1.8. Since the actual code I wrote wouldn’t make any sense to readers, I wrote a very easy-to-understand test case that reproduces the problem reliably, with lines 7 and 10 highlighted:

#!/usr/bin/ruby
# Encoding: UTF-8

foo = true

if foo
bar = 'something'
puts bar
else
[1, 2, 3].each { |bar| puts 'hello' }
end

The warning message, both from Rubocop under Ruby 1.9, and from multiple versions of Ruby via ruby -w natively:

jdc@ubuntu:~$ rvm list

rvm rubies

=* ruby-1.8.7-p374 [ x86_64 ]
ruby-1.9.3-p547 [ x86_64 ]
ruby-2.1.0 [ x86_64 ]
ruby-2.1-head [ x86_64 ]

# => - current
# =* - current && default
# * - default

jdc@ubuntu:~$ rvm 1.8.7-p374 do ruby -w ./x
something

jdc@ubuntu:~$ rvm 1.9.3-p547 do ruby -w ./x
./x:10: warning: shadowing outer local variable - bar
something

jdc@ubuntu:~$ rvm 2.1.0 do ruby -w ./x
./x:10: warning: shadowing outer local variable - bar
something

jdc@ubuntu:~$ rvm 2.1-head do ruby -w ./x
./x:10: warning: shadowing outer local variable - bar
something

jdc@ubuntu:~$ rvm 1.9.3-p547 do rubocop ./x
Inspecting 1 file
W

Offenses:

x:10:21: W: Shadowing outer local variable - bar
[1, 2, 3].each { |bar| puts 'hello' }
^^^

1 file inspected, 1 offense detected

I’m a C programmer (and also do assembly and Perl), so am quite familiar with -Wshadow, so the message itself made sense (most of what I found on Google were Ruby coders not understanding the message). But what didn’t make sense is that there was no shadowing violation here — the code within the if has a different scope than within the else. There is no way possible for these two to “share” scope, unless the language was horribly brain-damaged.

Simply renaming the variable bar (in either scope, but not both) rectifies the “problem”.

So, Ruby… do you simply not understand scope, or does your warning mode — which it appears very few people use (otherwise I’d have expected this to come up by now, and that’s pretty disappointing in itself) — simply have bugs (someone’s bison/yacc code is broken somewhere)?

It never ceases to amaze me how much advocacy there is for Ruby, that has either awful design decisions or bugs (it doesn’t matter to me which). Nothing’s perfect, but I would expect a language that’s been around since 1995 (with Ruby 1.8 being out as of late 2003) to have their ducks in order by now.