Reputation: 132
This is probably simple, but I don't understand why this statement isn't valid Ruby code:
3.>5 || 3.>2
SyntaxError: unexpected tINTEGER, expecting end-of-input
Why this one is:
3.>5 || 3.> #this seems nonsensical
=> false
And why by my book this one seems to give a misleading answer
3.>5 || 3.>(2)
=> false
Yet, this one gives the "right" answer
3.>(5) || 3.>(2)
=> true
Upvotes: 4
Views: 138
Reputation: 79813
The confusion here is due to using .
to make Ruby parse the comparisons as method calls, rather than the more normal binary operator such as 3 > 2
. In Ruby operators such as >
are ultimately handled as methods, but the parser has special cases to allow you to use the more familiar syntax.
If you imagine there is a method called gt
on integers, and you rewrite your examples using it instead of >
it might be clearer what it happening.
Your first example, 3.>5 || 3.>2
, will be equivalent to:
3.gt 5 || 3.gt 2
which Ruby tries to parse as
3.gt (5 || 3.gt) 2
That 2
at the end is the unexpected tINTEGER
that Ruby complains about.
The second example, 3.>5 || 3.>
will be parsed as something like this:
3.gt (5 || 3.gt)
This seems nonsensical because we know that gt
is really the binary operator >
and that it should have a second operator. Since Ruby is parsing it as if it was a method it has no way of knowing how many arguments there should be. As far as the parser knows the gt
method may not expect any arguments (we could have monkey patched >
to not expect an argument). Since the evaluation of the expression 5 || 3.>
short circuits to 5
, the 3.>
part is never executed so no error occurs.
If you write the same expression but without using .
, the Ruby parser knows that this is a binary operator and will expect the second operator:
eval '3>5 || 3 >'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
3>5 || 3 >
^
The last example, 3.>(5) || 3.>(2)
, would be parsed as:
3.gt(5) || 3.gt(2)
Because of the parentheses there is no ambiguity and it is clear that the 2
is an argument to the method call, so you get the correct answer.
Upvotes: 2
Reputation: 5343
Ruby is space sensitive and, unlike the syntax highlighter used in this website, Ruby employs "maximum munch" when parsing operators.
3.<
is different from 3. <
, because .<
parses as "send the < message to the integer 3."
Add a space. Better, never leave a dangling dot, for just this reason, and code 3.0 < 1
.
Next, 3.>5 || 3.>(2)
parses as 3.>(5 || 3.>(2))
, because of Ruby's magical disappearing parentheses. Follow your style guide, and add spaces around almost all binary operators. The few idiomatic ones where you shouldn't are .
, .&
, ..
, **
, etc...
Upvotes: 3