When I had a look into the ActiveRecord
source today, I stumbled upon these lines
name = -name.to_s
and
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
What purpose does the -
operator serve for on the symbol name
?
CodePudding user response:
That's String#-@
:
Returns a frozen, possibly pre-existing copy of the string.
Example:
a = "foo"
b = "foo"
a.object_id #=> 6980
b.object_id #=> 7000
vs:
a = -"foo"
b = -"foo"
a.object_id #=> 6980
b.object_id #=> 6980
CodePudding user response:
What purpose does the
-
operator serve for on the symbolname
?
You have your precedence rules wrong: the binary message sending operator (.
) has higher precedence than everything else, which means -
is not applied to the expression name
but to the expression name.to_s
.
In other words, you seem to think that this expression is parsed like this:
(-name).to_s
# which is the same as
name.-@().to_s()
but it is actually parsed as
-(name.to_s)
# which is the same as
name.to_s().-@()
Now, we don't know what name
is, but unless someone is seriously messing with you, #to_s
should return a String
. In other words, the operator is not applied to a Symbol
, as you thought.
Hence, we know that we are sending the message -@
to a String
and can thus look up what String#-@
does in the documentation:
-string
→frozen_string
Returns a frozen, possibly pre-existing copy of the string.
The returned String will be deduplicated as long as it does not have any instance variables set on it.
Dynamically created String
s are not frozen by default. Only static String
literals are, depending on your setting of the magic comment # frozen_string_literals: true
. String#-@
was added as an alias for String#freeze
to allow you to freeze and de-duplicate a String
with as little syntactic noise as possible.
The opposite operation is also available as String# @
.