views:

194

answers:

2

Why does this work the way it does? I thought it had something to do with pass-by-reference/value, but that's not the case. Does it have something to do with the new block scopes?

def strip_ids(array)
  array.each{ |row| row.reject! {|k, v| k =~ /_id/ } }
end

class Foo
  attr_accessor :array

  def initialize
    @array = []
    @array << { :some_id => 1, :something => 'one' }
    @array << { :some_id => 2, :something => 'two' }
    @array << { :some_id => 3, :something => 'three'}
  end
end

foo = Foo.new

puts strip_ids(foo.array).inspect

puts foo.array.inspect


##########################
#
# Output in ruby 1.8.7
#
# [{:some_id=>1, :something=>"one"}, {:some_id=>2, :something=>"two"}, {:some_id=>3, :something=>"three"}]
#
#
# Output in ruby 1.9.1
#
# [{:something=>"one"}, {:something=>"two"}, {:something=>"three"}]
#
+4  A: 

In 1.9 regular expressions apparently can match symbols.

$ ruby -v -e 'puts((:hello =~ /llo/).inspect)'
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
false
$ 19/bin/!!
19/bin/ruby -v -e 'puts((:hello =~ /llo/).inspect)'
ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]
2
$

If you do the regex op with k.to_s it will do the same thing on 1.8 and 1.9.

DigitalRoss
It's the first one. Do `k.to_s` in 1.8.7 and you'll be fine.
glenn mcdonald
Actually, I finally got around to building 1.9.1p243 and it also yields a symbol, so it must be the second explanation: regex now works on symbols. But as we noted, the solution is the same either way.
DigitalRoss
Mr Ross has it right.
Ryan Bigg
A: 

After digging into some of the C code for both versions of Ruby I can't seem to find where the relevant difference is. In Ruby 1.8.7 and 1.9.1 the =~ method is not defined for Symbol, but rather with Object. In 1.8.7 calling that method always returns false, while in 1.9.1 it always returns nil. Something must be different in how Symbols in 1.9.1 are recognized in for this particular operation since they are apparently type casted to Strings.

This is very odd behavior since it is completely undocumented and very different. I would suggest taking the question to the Ruby Core mailing list and see if any of the main hackers know what is going on.

James Thompson