开发者

Ruby 1.8 vs 1.9 - destructive reject! operator

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"}]
#


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜