为什么符号不是冻结的字符串?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (6)
  • 关注 (0)
  • 查看 (128)

我理解字符串和符号之间的理论区别。

比如JSON和HTTPCGI,使用的是字符串键,而不是符号键,所以Ruby程序必须向后弯曲,才能在前面或查找时转换这些键。仅仅存在于HashWithIndifferentAccess以及它在Rails和其他框架中的广泛使用,说明了这里存在一个问题,一个需要解决的问题。

有人能告诉我为什么符号不应该被冻结的实际原因吗?除了“因为这是一直是这样的”(历史上的)或“因为符号不是字符串”。

代码:

:apple == "apple"  #=> false, should be true

:apple.hash == "apple".hash #=> false, should be true

{apples: 10}["apples"]  #=> nil, should be 10

{"apples" => 10}[:apples]  #=> nil, should be 10

:apple.object_id == "apple".object_id #=> false, but that's actually fine

只需这样做:

class Symbol < String
  def initialize *args
    super
    self.freeze
  end

另见:

最新消息:我认为Matz为class Symbol < String在这里非常好:http://blde.nagaokaut.ac.jp/CGI-bin/scat.rb/ruby/rubycore/9192

提问于
用户回答回答于

Matz实现了Symbol类为Symbol < String.然后Symbol类被剥离,以消除任何可更改性。所以Symbol实际上是一个不变的String...

然而,它被恢复了。给出的理由是

尽管DuckTyping是非常反对的,但人们倾向于在类上使用CASE,而符号<String常常会导致严重的问题。

所以你的问题的答案仍然是:Symbol就像String___,但不是。

问题不在于Symbol不应该String但实际上,历史上并非如此。

用户回答回答于

如果字符串可以继承符号,因为它增加了许多功能(变异)。但是符号永远不能被用作字符串,因为在所有需要突变的情况下,它都会失败。

无论如何,正如我前面所说,字符串==符号绝不能像上面所建议的那样返回true。如果稍微考虑一下这一点,会注意到在一个类中不可能有合理的==实现子类实例也是如此。

用户回答回答于

它的基础是,这些不应该是真的:

:apple == "apple"  #=> false, should be true

:apple.hash == "apple".hash #=> false, should be true

符号总是相同的对象,而文本则不是。

用户回答回答于

主要原因:性能(符号以整数形式存储,从不垃圾收集)和一致性(:admin:admin将始终指向同一个对象,其中"admin""admin"(没有这种保证)等。

用户回答回答于

另一个考虑是"apple".each_char有道理,但是:apple.each_char不知道。字符串是一个“有序的字符列表”,但是符号是一个没有显式值的原子数据点。

我会说HashWithIndifferentAccess实际上,它演示了Ruby符号正在扮演两个不同的角色;符号(在本质上类似于其他语言的枚举)和内串(这本质上是一种先发制人的优化,弥补了Ruby被解释为没有智能优化编译器的好处。)

用户回答回答于

符号用于哈希键的原因之一是,给定符号的每个实例都是完全相同的对象。这意味着:apple.id将始终返回相同的值,即使没有传递它。另一方面,"apple".id每次都会返回不同的id,因为创建了一个新的String对象。

这就是为什么哈希键推荐使用符号的原因。使用符号时不需要进行对象等效性测试。它可以短路直接对象标识。

扫码关注云+社区

领取腾讯云代金券