Ruby中的冒号运算符是什么?


234

当我说时{ :bla => 1, :bloop => 2 },该:怎么办?我在某处读到了它与字符串的相似之处,但在某种程度上却是一个符号。

我对这个概念不太清楚,有人可以启发我吗?



7
尝试看一下:Ruby_Newbie符号指南
横街

该视频介绍了您需要了解的有关符号的所有信息。
totymedli

Answers:


249

:foo是一个名为“ foo”的符号。符号具有鲜明的特征,即任何两个相同的符号将是相同的:

"foo".equal? "foo"  # false
:foo.equal? :foo    # true

这使得比较两个符号的速度非常快(因为只涉及指针比较,而不是像字符串中那样比较所有字符),而且您不会在同一符号上成千上万个副本。

另外,与字符串不同,符号是不可变的。


2
只是想知道为什么原义字符串不支持字符串实习?
onmyway133 2014年

5
@ onmyway133因为Ruby的字符串是可变的。实习仅适用于不可变的值。
克里斯·杰斯特·杨

3
a)为什么是"foo".equal? "foo"假的?b)您能否在任何地方引用符号,从而使它们像全局变量一样?
Arc676 '16

2
@ Arc676 1. equal?在Ruby中进行身份比较。每个字符串文字(如"foo")都会创建一个新的字符串实例。之所以这样工作是因为Ruby中的字符串是可变的。2.符号是全局的,但是比全局变量更像全局常量,因为符号没有状态。因此,使用符号不是全局变量那样的反模式。
克里斯·杰斯特·杨

2
@ Arc676 "foo" == "foo"#=> true
Filip Bartuzi '17

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秒,因此我认为这是一次使用之间的洗礼。


非常有帮助!在我的系统上,==结果比.equal?字符串和符号比较要快。符号比较的结果比字符串比较快3倍以上。
melvynkim 2014年

33

符号是用红宝石表示字符串和名称的一种方式。

符号和字符串之间的主要区别在于,同名符号在红宝石会话期间仅初始化一次并在内存中仅存在一次。

当您需要使用相同的单词表示不同的事物时,它们很有用


19

著名的书《带有Rails的敏捷Web开发》中有一些引文,这也可能有助于理解该符号

Rails使用符号来识别事物。特别是,在命名方法参数并在哈希中查找内容时,它将它们用作键。

redirect_to :action => "edit", :id => params[:id]

您可以将符号视为神奇地制成常量的字符串文字。另外,您可以考虑冒号的意思是“命名的事物”,因此:id是“命名为ID的事物”。


5

在ruby中,每个对象都有一个唯一的对象标识符,如果您puts "hello".object_id在irb中写入并按两次return键,将获得2个不同的返回值,但是如果您写入:hello.object_id2次,则将仅获得相同的一个返回值。那应该解释了差异。


基本上,冒号运算符用于分配符号
Cesar Jr Rodriguez

2

如果使用:foo => bar,foo将是一个符号。符号的好处是它们是唯一的。当您调用哈希中的项目时,您会执行hash[:foo]

符号比字符串需要更少的内存,如果要使程序更快一点,这也使它们很有用。


0

这是一个象征。基本上,您是说哈希的两个元素都具有键blabloop,就好像您已经使用了字符串"bla"和一样"bloop"。但是,它们占用的内存比字符串少,并且更易于键入。


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对“裸词”的回答。


-1

如果您熟悉Java,您可能会知道Java中的字符串是不可变的。在Ruby中,符号在这种意义上是相似的。它们是不可变的,即特定符号出现的任何次数都:symbol将仅映射到单个存储器地址。因此,建议尽可能使用符号,因为它可以优化内存使用率。


1
符号是不可变的事实确保了它们在整个应用程序中始终是相同的实例,因此可以保证它们是同一对象。检查这些引用:troubleshooters.com/codecorn/ruby/symbols.htm robertsosinski.com/2009/01/11/... 你如果谷歌发现更多的信息负载。
Dhruva Sagar

我说的是您对Java的类比。Java字符串与符号不相似。Java字符串文字不是全部字符串。
smartnut007

也许我的陈述不够清楚。它们仅在它们是不变的这一事实上彼此相似。
德鲁瓦·萨加尔

@DhruvaSagar:如果使用Objective C的类比会更好NSString。这里"foo"将永远是等于"foo",因为内部字符串是相同的只是指向。不过,答案仍然令人困惑。
拉斐尔·布加杰夫斯基
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.