Unary minus seems to have special precedence when a numeric literal is involved. Is this documented behavior?
The precedence tables I've seen (e.g. here) don't even mention the dot (method-call) operator.
Test on ruby 2.3.6:
puts "=== literal integer ==="
# `-` has higher precedence than `.`
p( -1.abs ) # => 1
p( -(1.abs) ) # => -1 (previous line should match this if `.` had higher precedence)
puts "=== literal float ==="
# again `-` has higher precedence than `.`
p( -1.2.abs ) # => 1.2
p( -(1.2.abs) ) # => -1.2 (previous line should match this if `.` had higher precedence)
puts "=== integer in a variable ==="
(1).tap do |i|
# `.` has higher precedence
p( -i.abs ) # -1
p( (-i).abs ) # 1 (previous line should match this if `-` had higher precedence)
end
puts "=== float in a variable ==="
(1.2).tap do |i|
# `.` has higher precedence
p( -i.abs ) # -1.2
p( (-i).abs ) # 1.2 (previous line should match this if `-` had higher precedence)
end
puts "=== literal string ==="
'a'.frozen? == false or raise "frozen_string_literal must be disabled"
# Note that unary minus on Strings returns a frozen copy if the string wasn't already frozen
# `.` has higher precedence (differs from numeric precedence)
p( (-'a'.succ).frozen? ) # true
p( ((-'a').succ).frozen? ) # false (previous line should match this if `-` had higher precedence)
The reason is that in the literal number case, the - in front isn't an unary operator, but part of the literal syntax.
However, the - operator itself has lower precedence than method invocation. Given that there is no -'string' literal syntax for strings, this rule always applies regardless of if the string was literal or not.
class Integer
def -@
puts 'Called'
end
end
class String
def -@
puts 'Called'
end
end
-1 # nothing, the - wasn't an unary operation, but part of the number construction
x = 1
-x # Called
-'a' # Called
a = 'a'
-a # Called
Another interesting thing is that if you put a space between the number and the -, the - is no longer part of the literal syntax.
- 1 # Called
Here is the semantic explanation:
-1.- 1 accounts to "apply the unary minus to the number (positive) one".-'a' means "apply the unary minus to the string 'a'".If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With