IRB — синтаксис хэша Ruby 1.9.x: {if: true} не равно {:if =› true}

Короче говоря, я писал метод, который включал аргумент options, который будет делать определенные вещи, если значение для ключа :if оценивается как true. Когда я пытаюсь ввести хэш в IRB, используя новый синтаксис, я получаю синтаксическую ошибку в IRB, приглашение остается открытым:

1.9.3p374 :010 > {if: true}
1.9.3p374 :011?>

Используя старый синтаксис, работает просто отлично:

1.9.3p374 :011 > {:if => true}
 => {:if=>true} 

Все ключевые слова, с которых начинается оператор, ведут себя одинаково. Например. def, do, module, case

Другие зарезервированные слова, которые встречаются в середине и class, прекрасно работают: else, end.

Мой вопрос: это ожидаемое поведение, ошибка или ограничение?


person Leonel Galán    schedule 19.02.2013    source источник
comment
irb немного хрупок и имеет значительное повреждение мозга, вы, вероятно, видите некоторые из них.   -  person mu is too short    schedule 20.02.2013
comment
@muistooshort кажется довольно необоснованным. echo 'puts {if: true}.inspect' > test.rb; ruby test.rb возвращает: test.rb:1: syntax error, unexpected ':' Каким образом irb хрупок?   -  person nzifnab    schedule 20.02.2013
comment
@nzifnab Irb должен отложить выполнение оператора до end, и если он неправильно интерпретирует оператор управления (как здесь), возникают дополнительные уникальные проблемы.   -  person coreyward    schedule 20.02.2013
comment
О, ну, это достаточно справедливо :) Меня это всегда беспокоило, но, думаю, я никогда не обращал на это особого внимания.   -  person nzifnab    schedule 20.02.2013
comment
@nzifnab: Возможно, вам стоит попробовать вместо этого h = { if: 'b' };puts h.inspect.   -  person mu is too short    schedule 20.02.2013
comment
Интересный. Работает как скрипт, молчит при входе в IRB. Спасибо за пример :)   -  person nzifnab    schedule 20.02.2013


Ответы (1)


Сложно надежно и однозначно анализировать вещи на любом языке. Это особенно верно, когда вы начинаете использовать зарезервированные слова. И irb должен пойти дальше и предоставить интерактивную модель поверх парсера, что еще сложнее. Лично я не думаю, что слишком много стоит беспокоиться о подобных случаях, будь то пользователь языка или сопровождающий. На мой взгляд, лучше просто выяснить, что работает, и по возможности избегать подобных ситуаций.

Вы можете увидеть подобное поведение в простом Ruby, за пределами irb. Например:

puts({if: true})  # no problem, behaves as expected in Ruby 1.9.3.
puts {if: true}   # raises a syntax error in Ruby 1.9.3

Чтобы ответить на ваш вопрос, является ли это «ожидаемым поведением, ошибкой или ограничением», я бы сказал, что вы должны игнорировать irb и сравнивать его с обычным Ruby, и если вы сделаете это, он будет работать нормально. Это означает, что это должна быть ошибка irb.

Но возможно или стоит решить? @coreyward хорошо отмечает в своем комментарии, что irb должен откладывать выполнение в большинстве случаев, когда он сталкивается с if. Вам придется искать дальше, чтобы знать наверняка, но вы не сможете однозначно интерпретировать все подобные случаи.

Мой совет: избегайте этой конструкции вообще, если можете, и не используйте зарезервированные слова для меток, если можете этого избежать!

Вот файл, который вы можете запустить с помощью обычного Ruby (например, MRI). Вы должны увидеть {:if=>true} в выводе, чтобы подтвердить, что он работает.

{if: true}
foo = {if: true}
# if MRI is working, should be able to execute this file without trouble.
p foo
person Peter    schedule 19.02.2013
comment
Также стоит отметить, что если вы введете присваивание, все будет работать так, как ожидалось. Например. foo = {if: true} хорошо оценивает МРТ (хотя IRB все еще спотыкается). - person coreyward; 20.02.2013
comment
@coreyward: действительно. Я попробовал это. Я добавлю блок кода в свой ответ, чтобы уточнить. Спасибо! - person Peter; 20.02.2013
comment
Все очень интересно. Пример OP не работает, будь то в скрипте ruby ​​​​или в IRB, но когда вы заключаете в скобки путы, он работает. Как запутанно! Я почти хочу, чтобы они застряли исключительно на хэш-ракете. Намного легче понять и гораздо меньше ошибок (и тогда все хэши одинаковы, а не «хэши со строковыми ключами используют ракеты! хэши с зарезервированными метками используют ракеты! символы иногда должны использовать синтаксис меток!) Тьфу. - person nzifnab; 20.02.2013
comment
@nzifnab: иногда в вашем комментарии важно, вы не можете использовать стиль JavaScript с такими символами, как :$set, которые появляются повсюду, когда вы работаете с MongoDB. Я просто использую hashrocket, потому что я знаю, как печатать, и у меня есть более важные вещи, о которых нужно беспокоиться, чем когда я могу или не могу использовать нотацию в стиле JavaScript. - person mu is too short; 20.02.2013
comment
просто чтобы сбалансировать этот разговор - мне очень нравится новый синтаксис (стиль {a: 'b'}), потому что я думаю, что он действительно облегчает код и делает его более читаемым. Я использую его исключительно и редко попадаю в ловушки. Это не большая проблема. Я думаю об этом как о // против /* */ для однострочных комментариев C. - person Peter; 20.02.2013
comment
Спасибо за ответ, Петр, я возьму его. Я согласен с вами в том, что код выглядит чище, и я буду использовать его всякий раз, когда это возможно. - person Leonel Galán; 20.02.2013