Ответ 1
Есть несколько мест, где это может быть указано, т.е. Несколько вещей, которые считаются "Специфика языка Ruby":
- Спецификация языка Ruby ISO
- проект RubySpec
- YARV testsuite
- Книга программирования языка Ruby от matz и David Flanagan
Спецификация ISO ничего не говорит о порядке Hash
: она была написана таким образом, что все существующие реализации Ruby автоматически согласуются с ней, без необходимости изменения, т.е. Было написано, чтобы описать текущие реализации Ruby, а не предписывать. В то время, когда была написана спецификация, такие реализации включали МРТ, 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 был оставлен разработчиками из-за разочарования, что разработчики рубинового ядра и разработчики YARV так и не узнали его. Однако он (неявно) указывает, что литералы Hash
упорядочены слева направо:
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
и Hash#each
имеет тот же порядок.
Я не мог найти ничего в YARV testsuite, который указывает, что упорядочение сохраняется. На самом деле, я ничего не мог найти о заказе в этом testuite, совсем наоборот: тесты идут очень долго, чтобы избежать зависания от заказа!
Фланаган/Мац книга любопытное Сорта неявно указывает Hash
буквального упорядочение в разделе 9.5.3.6 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
и в другом комментарии, что
ничто иное не имело бы смысла
К сожалению, это не так:
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
Итак, в зависимости от того, как вы интерпретируете эту строку из книги и в зависимости от того, как "спецификация-иш" вы судите эту книгу, да, заказ литералов гарантирован.