Answers:
:foo
是一个名为“ foo”的符号。符号具有鲜明的特征,即任何两个相同的符号将是相同的:
"foo".equal? "foo" # false
:foo.equal? :foo # true
这使得比较两个符号的速度非常快(因为只涉及指针比较,而不是像字符串中那样比较所有字符),而且您不会在同一符号上成千上万个副本。
另外,与字符串不同,符号是不可变的。
"foo".equal? "foo"
假的?b)您能否在任何地方引用符号,从而使它们像全局变量一样?
equal?
在Ruby中进行身份比较。每个字符串文字(如"foo"
)都会创建一个新的字符串实例。之所以这样工作是因为Ruby中的字符串是可变的。2.符号是全局的,但是比全局变量更像全局常量,因为符号没有状态。因此,使用符号不是全局变量那样的反模式。
"foo" == "foo"
#=> true
只是为了演示答案中提到的一些内容:
require 'benchmark'
n = 1_000_000
print '"foo".equal? "foo" -> ', ("foo".equal? "foo"), "\n"
print '"foo" == "foo" -> ', ("foo" == "foo" ), "\n"
print ':foo.equal? :foo -> ', (:foo.equal? :foo ), "\n"
print ':foo == :foo -> ', (:foo == :foo ), "\n"
Benchmark.bm(10) do |b|
b.report('string') { n.times { "foo".equal? "foo" }}
b.report('str == str') { n.times { "foo" == "foo" }}
b.report('symbol') { n.times { :foo.equal? :foo }}
b.report('sym == sym') { n.times { :foo == :foo }}
end
运行它输出:
"foo".equal? "foo" -> false
"foo" == "foo" -> true
:foo.equal? :foo -> true
:foo == :foo -> true
因此,将一个字符串与使用一个字符串进行比较equal?
失败,因为它们是不同的对象,即使它们的内容相同。==
比较内容,用符号进行的等效检查要快得多。
user system total real
string 0.370000 0.000000 0.370000 ( 0.371700)
str == str 0.330000 0.000000 0.330000 ( 0.326368)
symbol 0.170000 0.000000 0.170000 ( 0.174641)
sym == sym 0.180000 0.000000 0.180000 ( 0.179374)
就速度而言,这两个符号测试基本相同。经过1,000,000次迭代后,仅相差0.004733秒,因此我认为这是一次使用之间的洗礼。
==
结果比.equal?
字符串和符号比较要快。符号比较的结果比字符串比较快3倍以上。
著名的书《带有Rails的敏捷Web开发》中有一些引文,这也可能有助于理解该符号:
Rails使用符号来识别事物。特别是,在命名方法参数并在哈希中查找内容时,它将它们用作键。
redirect_to :action => "edit", :id => params[:id]
您可以将符号视为神奇地制成常量的字符串文字。另外,您可以考虑冒号的意思是“命名的事物”,因此:id是“命名为ID的事物”。
在ruby中,每个对象都有一个唯一的对象标识符,如果您puts "hello".object_id
在irb中写入并按两次return键,将获得2个不同的返回值,但是如果您写入:hello.object_id
2次,则将仅获得相同的一个返回值。那应该解释了差异。
所有这些答案都省略了一个诱人的细节..如果您将符号:foo字符串化,则会得到..猜怎么着。字符串“ foo”。因此
irb(main):025:0>
irb(main):026:0> :foo
=> :foo
irb(main):027:0> "#{:foo}"
=> "foo"
irb(main):028:0>
irb(main):029:0> 'foo' <=> :foo
=> nil
irb(main):030:0> 'foo' <=> :foo.to_s
=> 0
irb(main):031:0>
因此,对于Perl程序员来说,这是Ruby对“裸词”的回答。
如果您熟悉Java,您可能会知道Java中的字符串是不可变的。在Ruby中,符号在这种意义上是相似的。它们是不可变的,即特定符号出现的任何次数都:symbol
将仅映射到单个存储器地址。因此,建议尽可能使用符号,因为它可以优化内存使用率。
NSString
。这里"foo"
将永远是等于"foo"
,因为内部字符串是相同的只是指向。不过,答案仍然令人困惑。