2013-07-18 10 views
2

следующих результатов кода в ошибкахРубин на рельсах - Рубин Приоритет операторов - Скобки

Пример 1

if params[:id] == '2' || params.has_key? :id 
    abort('params id = 2 or nothing') 
end 


syntax error, unexpected tSYMBEG, expecting keyword_then or ';' or '\n' 
if params[:id] == '2' || params.has_key? :id 

Однако переключении условных операторов || добавление скобок работает на 100%.

Пример 2

if params.has_key? :id || params[:id] == '2' 
    abort('params id = 2 or nothing') 
end 

Пример 3

if (params[:id] == '2') || (params.has_key? :id) 
    abort('params id = 2 or nothing') 
end 

Может кто-нибудь объяснить мне, почему Пример 1 приведет к ошибке?

Благодаря

ответ

4

Ваша проблема происходит на:

params[:id] == '2' || params.has_key? :id 

, которая может быть упрощенно:

:foo || some_method :bar 

, который вызывает ту же ошибку.Это выражение, в принципе, неоднозначный между

(:foo || some_method) :bar   (1) 

и

:foo || (some_method :bar)   (2) 

Когда выражение является неоднозначным, она решена другими факторами. Один из факторов, приоритет оператора ничего здесь не говорит о неоднозначности между (1) и (2). Следующим фактором является линейный порядок. Начиная с || появляется перед аргументом приложение () (опущено) в рассматриваемом выражении, первое применяется перед последним. Следовательно, выражение интерпретируется как (1). Так как (:foo || some_method) будет анализироваться как выражение, рядом будут два выражения. Это неграмматично, так же как:

:baz :bar 

является неграмматическим.

В самом деле, если вы переключитесь на заказ, как:

some_method :bar || :foo 

тогда, это будет истолковано как

(some_method :bar) || :foo 

по той же причине, и синтаксическая ошибка исчезнет.

Кроме того, когда вы устранить неоднозначность, явно с помощью скобок для обозначения приложения аргумента:

:foo || some_method(:bar) 

тогда нет никакой двусмысленности необходимо решить, и ошибка синтаксиса исчезает.

+0

Спасибо за великолепное объяснение. Это полезная ссылка: http://www.techotopia.com/index.php/Ruby_Operator_Precedence –

0

Это связано с тем, как Ruby оценивает, что if заявление.

Пример 1 подобен if (params[:id] == '2' || params.has_key?) :id

, который решает в неожиданной ошибки символа, как вы можете увидеть syntax error, unexpected tSYMBEG.

+1

Даже без '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' –

+0

Спасибо, что ответили. Почему он игнорирует: id в примере 1? –

+0

это как рубин оценивает код – gmaliar

0

Как говорит парень ... парсер не предполагает, что символ является параметром для has_key? Метод

Вы можете обойти ошибку явно кодирования скобки

if params[:id] == '2' || params.has_key?(:id) 
+0

ИМХО, это глупое предположение сделать, учитывая, что has_key ВСЕГДА нужен параметр? 100% Согласитесь, что добавление круглых скобок будет работать, это просто запутывает, когда вам нужны (лучшие практики) круглые скобки, а когда нет. –

+0

ой, для этого я получил понижение? :) Парсер не обязательно знает, что has_key? требуется параметр .. он может быть пользовательским методом. Вне рук я не могу думать о законной конструкции 'if condition_a || condition_b: symbol', так что эй, это может быть «ошибка» в аналитике Ruby ... Я не знаю, было ли это сообщено так для команды рубинового ядра с помощью redmine. – SteveTurczyn

+0

. Разве меня не меня понизило;) У меня недостаточно очков репутации. Ответ @sawa кажется законным, хотя я не согласен с тем, как Ruby анализирует этот код. –

1

Ваш :id символ в Ruby.

a = {'id' => 'a', 'value' => 'value'} 

a.has_key? 'id' 
=> true 

a.has_key? :id 
=> false 

Таким образом, вы должны изменить свой код:

if params[:id] == '2' or params.has_key? 'id' 
    abort('params id = 2 or nothing') 
end 

Примечание: Если вы собираетесь использовать эту проверку для ключа кода перед проверкой значение имеет больше смысла.

Примечание # 2: Испытано с:

params = {'id' => 'a', 'value' => 'value'} 

if params[:id] == '2' or params.has_key? 'id' 
    abort('params id = 2 or nothing') 
end 

и Руби 2.0.0

Также проверьте this question для получения дополнительной информации о Руби символов.

+1

плюс 1 для проверки ключа до значения – SteveTurczyn

+0

Изменение кода вашего предложения приводит к той же ошибке. –

+0

@ user2594899 Я изменил || оператор к и/или предоставленному и примерному коду. –

Смежные вопросы