Home > Enterprise >  What does the "-" mean in front of a ruby symbol?
What does the "-" mean in front of a ruby symbol?

Time:03-21

When I had a look into the ActiveRecord source today, I stumbled upon these lines

name = -name.to_s

https://github.com/rails/rails/blob/2459c20afb508c987347f52148210d874a9af4fa/activerecord/lib/active_record/reflection.rb#L24

and

ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)

https://github.com/rails/rails/blob/2459c20afb508c987347f52148210d874a9af4fa/activerecord/lib/active_record/reflection.rb#L29

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 symbol name?

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:

-stringfrozen_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 Strings 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# @.

  • Related