Путаница здесь связана с использованием .
, чтобы заставить Ruby анализировать сравнения как вызовы методов, а не с более обычным двоичным оператором, таким как 3 > 2
. В Ruby операторы, такие как >
, в конечном итоге обрабатываются как методы , но синтаксический анализатор имеет особые случаи, позволяющие использовать более знакомый синтаксис.
Если вы представляете, что есть метод с именем gt
для целых чисел, и вы переписываете свои примеры, используя его вместо >
, это может быть более понятно, что происходит.
Ваш первый пример, 3.>5 || 3.>2
, будет эквивалентен:
3.gt 5 || 3.gt 2
который Ruby пытается разобрать как
3.gt (5 || 3.gt) 2
То, что 2
в конце - это unexpected tINTEGER
, на который жалуется Руби.
Второй пример, 3.>5 || 3.>
будет проанализирован примерно так:
3.gt (5 || 3.gt)
Это кажется бессмысленным, потому что мы знаем, что gt
на самом деле является бинарным оператором >
и что у него должен быть второй оператор. Поскольку Ruby анализирует его так, как если бы он был методом, он не может знать, сколько аргументов должно быть. Поскольку синтаксический анализатор знает, что метод gt
может не ожидать каких-либо аргументов (мы могли бы сделать исправление для обезьяны >
, чтобы не ожидать аргумента). Так как вычисление выражения 5 || 3.>
замыкает на 5
, часть 3.>
никогда не выполняется, поэтому ошибки не возникает.
Если вы пишете то же выражение, но без использования .
, синтаксический анализатор Ruby знает, что это бинарный оператор, и будет ожидать второй оператор:
eval '3>5 || 3 >'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
3>5 || 3 >
^
Последний пример, 3.>(5) || 3.>(2)
, будет проанализирован как:
3.gt(5) || 3.gt(2)
Из-за круглых скобок нет никакой двусмысленности, и ясно, что 2
является аргументом для вызова метода, поэтому вы получите правильный ответ.