有几个位置可以指定,即一些被认为是“Ruby 语言规范”的东西:
ISO 规范没有提到任何关于Hash 排序的内容:它的编写方式是所有现有的 Ruby 实现都自动符合它,而无需更改,即它被编写为描述性的 的当前 Ruby 实现,而不是 规范的。在编写规范时,这些实现包括 MRI、YARV、Rubinius、JRuby、IronRuby、MagLev、MacRuby、XRuby、Ruby.NET、Cardinal、tinyrb、RubyGoLightly、SmallRuby、BlueRuby 等。特别感兴趣的是 MRI(only 实现 1.8)和 YARV(only 实现 1.9(当时)),这意味着规范只能指定以下行为1.8 和 1.9 通用,Hash 排序不是。
RubySpec 项目被其开发人员放弃,因为 ruby 核心开发人员和 YARV 开发人员从未认识到它。但是,它确实(隐含)specify that Hash literals are ordered left-to-right:
new_hash(1 => 2, 4 => 8, 2 => 4).keys.should == [1, 4, 2]
这是Hash#keys 的规范,但是,其他规范测试Hash#values 与Hash#keys 具有相同的顺序,Hash#each_value 和Hash#each_key 具有相同的顺序,并且Hash#each_pair 和@ 987654340@也有同样的顺序。
我在the YARV testsuite 中找不到任何指定保留顺序的内容。事实上,我在那个测试套件中根本找不到任何关于排序的信息,恰恰相反:测试会根据排序花费很长时间来避免!
Flanagan/matz 的书在 9.5.3.6 Hash 迭代器部分中隐含地指定了 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
在his comment、@mu is too short 中提到
h = { a: 1, b: 2 } 与h = { }; h[:a] = 1; h[:b] = 2 相同
在another comment那个
没有任何意义
很遗憾,事实并非如此:
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
因此,取决于您如何解释书中的那一行以及您如何判断该书的“规范”,是的,文字的顺序是有保证的。