Почему выражение (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