ruby 符号前的“-”是什么意思?

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

今天查看 ActiveRecord 源代码时,我偶然发现了这些行

name = -name.to_s

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

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

- 运算符在符号 name 上的作用是什么?

那是 String#-@:

Returns a frozen, possibly pre-existing copy of the string.

示例:

a = "foo"
b = "foo"

a.object_id #=> 6980
b.object_id #=> 7000

对比:

a = -"foo"
b = -"foo"

a.object_id #=> 6980
b.object_id #=> 6980

What purpose does the - operator serve for on the symbol name?

您的优先级规则有误:二进制消息发送运算符 (.) 的优先级高于其他所有运算符,这意味着 - 而不是 应用于表达式 name 但应用于表达式 name.to_s.

换句话说,你似乎认为这个表达式是这样解析的:

(-name).to_s
# which is the same as
name.-@().to_s()

但实际上被解析为

-(name.to_s)
# which is the same as
name.to_s().-@()

现在,我们不知道 name 是什么,但除非有人像你想的那样认真地惹你,#to_s should return a String. In other words, the operator is not applied to a Symbol

因此,我们知道我们正在将消息 -@ 发送到 String,因此可以在文档中查找 String#-@ 做了什么:

-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.

动态创建的 String 默认不冻结。仅静态 String 字面值,具体取决于您对魔术注释 # frozen_string_literals: true 的设置。 String#-@ 被添加为 String#freeze 的别名,以允许您冻结和 de-duplicate 一个 String,语法噪音尽可能少。

相反的操作也可用String#+@