【发布时间】:2011-09-14 08:08:03
【问题描述】:
当我说{ :bla => 1, :bloop => 2 } 时,: 到底是做什么的?我在某处读到它与字符串的相似之处,但不知何故是一个符号。
我对这个概念不是很清楚,有人可以启发我吗?
【问题讨论】:
-
This video 告诉你关于符号你需要知道的一切。
当我说{ :bla => 1, :bloop => 2 } 时,: 到底是做什么的?我在某处读到它与字符串的相似之处,但不知何故是一个符号。
我对这个概念不是很清楚,有人可以启发我吗?
【问题讨论】:
:foo 是一个名为“foo”的符号。符号有一个显着的特点,即任何两个同名的符号都是相同的:
"foo".equal? "foo" # false
:foo.equal? :foo # true
这使得比较两个符号非常快(因为只涉及指针比较,而不是像在字符串中比较所有字符),而且您不会有无数个相同符号的副本漂浮。
此外,与字符串不同,符号是不可变的。
【讨论】:
"foo".equal? "foo" 是假的? b) 你能在任何地方引用一个符号,本质上使它们像全局变量吗?
equal? 进行身份比较。每个字符串文字,如@987654325@,都会创建一个新的字符串实例。之所以如此,是因为 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 倍以上。
符号是在 ruby 中表示字符串和名称的一种方式。
符号和字符串之间的主要区别在于,同名符号在 ruby 会话期间被初始化并且仅在内存中存在一次。
当您需要使用同一个词来表示不同的事物时,它们很有用
【讨论】:
引用名著Agile Web Development with Rails中的一些名言,可能也有助于理解符号:
Rails 使用符号来识别事物。特别是,它在命名方法参数和在哈希中查找内容时使用它们作为键。
redirect_to :action => "edit", :id => params[:id]
您可以将符号视为神奇地变成常量的字符串文字。或者,您可以认为冒号表示“命名的事物”,因此 :id 是“命名为 id 的事物”。
【讨论】:
在 ruby 中,每个对象都有一个唯一的对象标识符,如果你在你的 irb 中写 puts "hello".object_id 并点击返回 2 次不同的时间,你会得到 2 个不同的返回值,但如果你写 :hello.object_id 2 次你只会得到相同的返回值。
这应该可以解释差异。
【讨论】:
如果你使用:foo => bar,foo 将是一个符号。符号的好处是它们是独一无二的。当您调用哈希中的一个项目时,您执行hash[:foo]。
符号比字符串需要更少的内存,如果你想让你的程序更快一点,它们也很有用。
【讨论】:
这是一个符号。基本上,您是说散列的两个元素具有键 bla 和 bloop,就像您使用字符串 "bla" 和 "bloop" 一样。但是,它们比字符串占用更少的内存,并且更容易输入。
【讨论】:
如果您熟悉 Java,您可能知道 Java 中的字符串是不可变的。在 Ruby 中,符号在这个意义上是相似的。它们是不可变的,即特定符号:symbol 的任何出现次数将仅映射到单个内存地址。因此,建议尽可能使用符号,因为它可以优化内存使用。
【讨论】:
NSString,这个类比会更好。 "foo" 将始终等于 "foo",因为内部相同的字符串只是被指向。不过,答案仍然令人困惑。
所有这些答案都省略了一个额外的诱人细节..如果您将符号 :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 对“裸词”的回答。
【讨论】: