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

mah*_*off 30 ruby sorting hash loops literals

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

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

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

Jör*_*tag 31

有几个地方这个位置可以指定,即一对夫妇被认为是"Ruby语言规范"的事情:

ISO规范没有Hash提及任何有关排序的内容:它是以这样的方式编写的:所有现有的Ruby实现都自动符合它,而不必更改,即它被编写为描述当前的Ruby实现,而不是规定性的.在编写规范时,这些实现包括MRI,YARV,Rubinius,JRuby,IronRuby,MagLev,MacRuby,XRuby,Ruby.NET,Cardinal,tinyrb,RubyGoLightly,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]
Run Code Online (Sandbox Code Playgroud)

Hash#keys然而,这是与其他规格测试Hash#values具有相同顺序的规格Hash#keys,Hash#each_value并且Hash#each_key具有相同的顺序,Hash#each_pair并且Hash#each具有相同的顺序.

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

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

但是,在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
Run Code Online (Sandbox Code Playgroud)

他的评论中,@ mu太短

h = { a: 1, 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
Run Code Online (Sandbox Code Playgroud)

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


Exu*_*ery 10

文档:

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

  • Ruby解析器必须解析文字.虽然最明显的方法是从上到下,但可能有许多优化相关的原因,为什么它可以以不同的顺序这样做.此外,Ruby 1.9订单规则适用于Ruby代码; 它不一定适用于Ruby的内部可能用哈希做的事情(即使Ruby从上到下插入,也不意味着保留了顺序). (7认同)
  • 是的,正如问题所提到的,但我指的是 *literal* 符号。 (3认同)
  • 字面符号没有什么不同/特别之处.它将它们(按提供的顺序)添加到哈希(因此将以相同的顺序枚举),请参阅https://github.com/ruby/ruby/blob/trunk/hash.c#L550-L633 (3认同)
  • 这是一个 Ruby 实现。我不知道有任何测试。无论如何都支持代码引用。 (3认同)
  • 为什么_literal_符号会有所作为?它不像文字符号创建不同类型的哈希,它仍然是哈希. (3认同)