当我说{ :bla => 1, :bloop => 2 }
时,:
究竟做了什么?我在某处读到了它与字符串的相似之处,但不知何故是一个符号。
我对这个概念不是很清楚,有人可以启发我吗?
答案 0 :(得分:239)
:foo
是一个名为“foo”的符号。符号具有明显的特征,即任何两个名称相同的符号都是相同的:
"foo".equal? "foo" # false
:foo.equal? :foo # true
这使得比较两个符号的速度非常快(因为只涉及指针比较,而不是像比较字符串中的所有字符),而且你不会有相同符号浮动的无数副本。
此外,与字符串不同,符号是不可变的。
答案 1 :(得分:44)
只是为了演示答案中提到的一些内容:
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秒的差异,所以我说这是一个可以使用的清洗。
答案 2 :(得分:30)
符号是一种在ruby中表示字符串和名称的方法。
符号和字符串之间的主要区别在于,在ruby会话期间,初始化了同名符号并且只在内存中存在一次。
当您需要使用相同的词来表示不同的内容时,它们非常有用
答案 3 :(得分:16)
着名的书籍Agile Web Development with Rails中有一些引用,这可能有助于理解符号:
Rails使用符号来识别事物。特别是,它在命名方法参数和在哈希中查找时将它们用作键。
redirect_to :action => "edit", :id => params[:id]
您可以将符号视为神奇地制作为常量的字符串文字。或者,您可以将冒号视为“名为”的东西,因此:id是“名为id的东西”。
答案 4 :(得分:4)
在ruby中,每个对象都有一个唯一的对象标识符,如果你在你的irb中写puts "hello".object_id
并点击返回2个不同的时间,你会得到2个不同的返回值,但如果你写:hello.object_id
2时间你只会获得相同的返回值。
这应该解释了差异。
答案 5 :(得分:2)
如果您使用:foo => bar
,则foo将是一个符号。符号的好处是它们是独一无二的。当您调用哈希中的项目时,您执行hash[:foo]
。
符号需要的内存少于字符串,如果你想让你的程序更快一点,这也会有用。
答案 6 :(得分:0)
这是一个象征。基本上,您说哈希的两个元素具有键bla
和bloop
,就像您使用了字符串"bla"
和"bloop"
一样。但是,它们占用的内存少于字符串,并且更容易键入。
答案 7 :(得分:0)
所有这些答案都省略了一个诱人的细节..如果您将符号: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对“裸词”的回答。
答案 8 :(得分:-1)
如果您熟悉Java,您可能会意识到Java中的字符串是不可变的。在Ruby中,符号在这个意义上是相似的。它们是不可变的,即,特定符号:symbol
的任何数量的出现将仅映射到单个存储器地址。因此,建议尽可能使用符号,因为它可以优化内存使用。