是否保证Ruby哈希文字的顺序?

Ruby,自v1.9起,在循环哈希时支持确定性顺序; 首先添加的条目将首先返回。

这是否适用于文字,即{ a: 1, b: 2 }总是在b之前产生?

我做了一个Ruby 2.1(MRI)的快速实验,它实际上是一致的,但是语言在多大程度上保证了所有Ruby实现的工作?

可以指定几个位置,即一些被认为是“Ruby语言规范”的东西:

  • ISO Ruby语言规范
  • RubySpec项目
  • YARV测试套件
  • 由matz和David Flanagan撰写的Ruby Programming Language一书

ISO规范没有提及任何关于Hash排序的内容:它是以这样的方式编写的,即所有现有的Ruby实现都自动符合它,而不必更改,即它被编写为描述当前的Ruby实现,而不是规定性的 。 在编写规范时,这些实现包括MRI,YARV,Rubinius,JRuby,IronRuby,MagLev,MacRuby,XRuby,Ruby.NET,Cardinal,tinyrb,RubyGoLight,SmallRuby,BlueRuby等。 特别感兴趣的是MRI( 实现1.8)和YARV( 实现1.9(当时)),这意味着规范只能指定1.8和1.9共有的行为,而Hash排序则不然。

RubySpec项目被开发人员抛弃了,因为ruby-core开发人员和YARV开发人员从未认识到它。 但是,它(隐式地) 指定Hash文字从左到右排序 :

 new_hash(1 => 2, 4 => 8, 2 => 4).keys.should == [1, 4, 2] 

这是Hash#keys的规范,然而,其他规格测试Hash#valuesHash#keys具有相同的顺序, Hash#each_valueHash#each_key具有与那些相同的顺序,并且Hash#each_pairHash#each都有同样的顺序。

我在YARV测试套件中找不到任何指定保留排序的东西。 事实上,我在测试套件中找不到任何关于订购的东西恰恰相反:测试需要很长时间以避免依赖于订购!

Flanagan / matz book kinda-sorta在9.5.3.6Hash迭代器中隐式指定了Hash文字排序。 首先,它使用与文档大致相同的公式:

但是,在Ruby 1.9中,哈希元素按其插入顺序进行迭代,[…]

但接着它继续:

[…],这就是以下示例中显示的顺序:

在这些示例中,它实际上使用了一个文字:

 h = { :a=>1, :b=>2, :c=>3 } # The each() iterator iterates [key,value] pairs h.each {|pair| print pair } # Prints "[:a, 1][:b, 2][:c, 3]" # It also works with two block arguments h.each do |key, value| print "#{key}:#{value} " # Prints "a:1 b:2 c:3" end # Iterate over keys or values or both h.each_key {|k| print k } # Prints "abc" h.each_value {|v| print v } # Prints "123" h.each_pair {|k,v| print k,v } # Prints "a1b2c3". Like each 

在他的评论中 , @ mu太短了

h = { a: 1, b: 2 }h = { }; h[:a] = 1; h[:b] = 2相同h = { }; h[:a] = 1; h[:b] = 2 h = { }; h[:a] = 1; h[:b] = 2

并在另一个评论中说

没有别的意义

不幸的是,事实并非如此:

 module HashASETWithLogging def []=(key, value) puts "[]= was called with [#{key.inspect}] = #{value.inspect}" super end end class Hash prepend HashASETWithLogging end h = { a: 1, b: 2 } # prints nothing h = { }; h[:a] = 1; h[:b] = 2 # []= was called with [:a] = 1 # []= was called with [:b] = 2 

所以,根据你如何从书中解释这一行,并根据“规范 – 是什么”来判断那本书,是的,文字的排序是有保证的。

从文档 :

哈希按照插入相应键的顺序枚举其值。