Почему выражение (true == true == true) вызывает синтаксическую ошибку?
Рубин:
true == true == true
синтаксическая ошибка, неожиданный tEQ
по сравнению с JavaScript:
true == true == true
// => true
против C:
1 == 1 == 1
// => 1
Ответы
Ответ 1
Направление ассоциации, которое контролирует порядок операторов, имеющих свои аргументы, не определено для метода ==
, аналогично методам ===
!=
, =~
И <=>
(все из которых имеют одинаковый приоритет и образуют отдельную группу приоритетов исключительно).
Документация
Таким образом, порядок оценки в случае, когда несколько операторов из упомянутого выше списка связаны цепью в строке, должны быть явно заданы через
-
скобка ()
:
(true == true) == true # => true
true == (true == true) # => true
-
или точечный оператор .
(для последней проверки равенства в строке может быть опущено):
true .== true == true # => true
Ответ 2
TL; DR Синтаксис подразумевает, что все 3 значения равны, это не то, что он делает в javascript или C, поэтому, когда Ruby дает синтаксическую ошибку, дверь открыта для этого, чтобы это было реализовано в будущем.
Если я правильно понял вопрос value_a == value_b == value_c
должен возвращать true только в том случае, если все они являются eqel, используя == в качестве средства сравнения, как показано в этом методе
# version 1
def compare_3_values(a, b, c)
a == b && a == c && b == c
end
однако есть еще один возможный ожидаемый результат. для реализации этого, как показано в предыдущем ответе:
#version 2
def compare_3_values(a, b, c)
(a == b) == c
end
Результаты - миры друг от друга.
JavaScript всегда использует версию 2, которая довольно бесполезна, поскольку третий элемент всегда сравнивается с истинным или ложным (0 или 1, если третий элемент является целым числом), поэтому false == false == true
возвращает true.
чтобы гарантировать, что если метод является одним из трех значений, которые он вызывает только один раз, мы должны создать копию (а не ссылку) всех трех переменных, а затем выполнить сравнения следующим образом:
def compare_3_values(a_original, b_original, c_original)
#duplicate all three values as a, b, c
a, b, c = a_original.dup, b_original.dup, c_original.dup
a == b && b == c && a == c
end
Хорошей новостью является то, что, поскольку Ruby дает синтаксическую ошибку, это единственный язык, который может реализовать это, не нарушая каждый код.
для любого другого языка он сломал бы так много кода, что даже если бы он был реализован в более поздней крупной версии, необходимо было бы установить флаг/параметр, чтобы включить или выключить его на долгие годы, поэтому он никогда не будет стоящим.
Некоторые интересные результаты в Ruby
false .== false == true
=> true
false .== true == false
=> true
true .== false == false
=> true
false .== false == false
=> false
true .== true == false
false
И в javascript
false == false == true
=> true
false == true == false
=> true
true == false == false
=> true
false == false == false
=> false
true == true == false
=> false
Редактирование, протестированное на C, также похоже на JavaScript, поскольку оно сравнивает результат первых двух значений с третьим значением
Ответ 3
Первый ответ превосходный, но на всякий случай это не совсем понятно (и люди спрашивают, почему), вот еще несколько примеров.
В C оператор ==
является ассоциативным слева-направо, а boolean представляется как 1 (true) и 0 (false), поэтому первый 1 == 1
оценивает 1
(true), а затем вы оцениваете результат первое выражение со вторым. Ты можешь попробовать:
2 == 2 == 2 // => 0
Что в C, оценивается как:
(2 == 2) == 2
1 == 2 // => 0
В Javascript, аналогично C, ==
слева направо ассоциативен. Попробуем с 0 на этот раз (хотя тот же пример из C тоже будет работать):
0 == 0 == 0
false
Снова:
0 == 0 == 0
true == 0 // => false
В Ruby ==
не имеет ассоциативных свойств, т.е. он не может использоваться несколько раз в одном выражении, поэтому выражение не может быть оценено. Почему это решение было принято, это вопрос для автора языка. Кроме того, Ruby не определяет числовой 1 как логическое, поэтому 1 == true
оценивает значение false.
Во втором ответе говорится, что в Ruby есть некоторые "странные" случаи, но все они оценивают как ожидалось:
(1 == 1) == 1
true == 1 # => false
1 == (1 == 1)
1 == true # => false
1 .== 1 == 1
(1 == 1) == 1
true == 1 # => false
false .== false == true
(false == false) == true
true == true # => true
false .== true == false
(false == true) == false
false == false # => true
true .== false == false
(true == false) == false
false == false # => true
false .== false == false
(false == false) == false
true == false # => false
true .== true == false
(true == true) == false
true == false # => false