Почему этот строковый ключ в хеше преобразован в символ?

Использование Ruby 2.3:

В примере 1 строковый ключ "a" автоматически преобразуется в символ, тогда как в примере 2 он остается строкой.

Пример 1

{"a": 1}
# => {:a=>1} 

Пример 2.

{"a"=>"c"}
# => {"a"=>"c"}

Я думал : был таким же, как и в старом стиле хэш - ракетном => синтаксис. Что происходит? Почему я никогда не замечал этого в Rails? Является ли это HashWithIndifferentAccess, скрывающим это?

Ответ 1

В Ruby 2.3 (.0) все они одинаковы:

{:"a" => 1}
{"a": 1},
{:a => 1}
{a: 1} 

Все они переводятся на одно и то же: a - это символ во всех этих случаях.

{"a"=>1} отличается: a - это строка в этом случае.

Ответ 2

Это из-за нового синтаксиса хэша, введенного с ruby 1.9. Синтаксис с двоеточием работает только с символьными клавишами. Он называл хеш "символом к объекту", и это только синтаксический сахар для наиболее распространенного стиля хэшей. Еще один момент для меня, он ближе к нотации объектов javascript.

Если у меня есть смешанные типы ключей, то я предпочитаю старый стиль (синтаксис хэш-ракеты), но это зависит от вас. Смешивание двух стилей выглядит уродливо для меня.

Ответ 3

Согласно документации Ruby:

Объекты Blockquote Symbol представляют имена и некоторые строки внутри интерпретатора Ruby. Они генерируются с использованием синтаксиса: name и: "string", а также различными методами to_sym. [...]

Это означает, что запуск:

$ ruby -e ruby -e "h = {key: \"value\"}; puts h"
$ ruby -e ruby -e "h = {:key => \"value\"}; puts h"
$ ruby -e ruby -e "h = {\"key\": \"value\"}; puts h"
$ ruby -e ruby -e "h = {:\"key\" => \"value\"}; puts h"
$ ruby -e ruby -e "h = {\"#{:key}\": \"value\"}; puts h"

Выдает тот же результат:

$ {:key=>"value"}