【发布时间】:2012-06-20 13:59:44
【问题描述】:
我了解字符串和符号之间的理论区别。我知道符号是用来表示概念或名称或标识符或标签或键的,而字符串是一袋字符。我知道字符串是可变的和瞬态的,而符号是不可变的和永久的。我什至喜欢在我的文本编辑器中 Symbols look 与 Strings 的不同之处。
困扰我的是,实际上,Symbol 与字符串非常相似,以至于它们没有实现为字符串这一事实引起了很多头痛。它们甚至不支持鸭式输入或隐式强制,不像其他著名的“相同但不同”的一对,Float 和 Fixnum。
当然,最大的问题是从其他地方进入 Ruby 的哈希值,如 JSON 和 HTTP CGI,使用字符串键,而不是符号键,因此 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
要让下一代 Ruby 主义者不那么困惑,只需这样做:
class Symbol < String
def initialize *args
super
self.freeze
end
(以及许多其他库级别的黑客攻击,但仍然不太复杂)
另见:
- http://onestepback.org/index.cgi/Tech/Ruby/SymbolsAreNotImmutableStrings.red
- http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol
- Why does my code break when using a hash symbol, instead of a hash string?
- Why use symbols as hash keys in Ruby?
- What are symbols and how do we use them?
- Ruby Symbols vs Strings in Hashes
- Can't get the hang of symbols in Ruby
- http://blog.arkency.com/could-we-drop-symbols-from-ruby/
- Do Ruby symbols exist because strings are mutable and not interned?
更新:我认为 Matz 在这里很好地说明了 class Symbol < String 的情况:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/9192(感谢 Azolo 挖掘这个问题,以及 Matz 最终撤回)。
【问题讨论】:
-
好问题!我记得当我开始学习 ruby 时被这个问题所困扰。但是随着时间的流逝,我只是忘记了它
-
+1 用于正确使用“乞求问题”(以及一个通常清晰且表达良好的问题)
-
{apples: 10}["apples"]应该是 10?所以{1 => "foo"}[1.0]应该是"foo",因为您提到Fixnum和Float作为“正确”完成的类的示例? -
我很困惑。在您的第一段中,您非常详细地解释了为什么符号和字符串根本不同,完全不同,彼此完全不同。然后,在第二段中,您声称它们几乎相同?
-
Jörg,它们的相似之处在于如果符号不存在,它们的功能几乎可以通过使用(冻结)字符串来完全复制。它们在语义上不同,但在功能上非常相似,大多数新手都惊讶于它们不相关。就像 JavaScript 没有整数类型(所有 JS 数字都是浮点数)一样,Ruby 也可以没有符号类型。再举一个例子,Stack 与 Array 不同,但 Matz 对 Array 添加 push 和 pop 没有问题;以同样的方式,一个字符串可以表现得像一个符号(并且没有额外的方法)。