【问题标题】:What is the colon operator in Ruby?什么是 Ruby 中的冒号运算符?
【发布时间】:2011-09-14 08:08:03
【问题描述】:

当我说{ :bla => 1, :bloop => 2 } 时,: 到底是做什么的?我在某处读到它与字符串的相似之处,但不知何故是一个符号。

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

【问题讨论】:

标签: ruby symbols


【解决方案1】:

:foo 是一个名为“foo”的符号。符号有一个显着的特点,即任何两个同名的符号都是相同的:

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

这使得比较两个符号非常快(因为只涉及指针比较,而不是像在字符串中比较所有字符),而且您不会有无数个相同符号的副本漂浮。

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

【讨论】:

  • 只是想知道为什么文字字符串不支持字符串实习?
  • @onmyway133 因为 Ruby 的字符串是可变的。实习仅适用于不可变值。
  • a) 为什么"foo".equal? "foo" 是假的? b) 你能在任何地方引用一个符号,本质上使它们像全局变量吗?
  • @Arc676 1. Ruby 中的equal? 进行身份比较。每个字符串文字,如@9​​87654325@,都会创建一个新的字符串实例。之所以如此,是因为 Ruby 中的字符串是可变的。 2. 符号是全局的,但更像是全局常量而不是全局变量,因为符号没有状态。因此,使用符号不像全局变量那样是一种反模式。
  • @Arc676 "foo" == "foo" # => true
【解决方案2】:

只是为了演示答案中提到的一些事情:

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 倍以上。
【解决方案3】:

符号是在 ruby​​ 中表示字符串和名称的一种方式。

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

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

【讨论】:

    【解决方案4】:

    引用名著Agile Web Development with Rails中的一些名言,可能也有助于理解符号

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

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

    您可以将符号视为神奇地变成常量的字符串文字。或者,您可以认为冒号表示“命名的事物”,因此 :id 是“命名为 id 的事物”。

    【讨论】:

      【解决方案5】:

      在 ruby​​ 中,每个对象都有一个唯一的对象标识符,如果你在你的 irb 中写 puts "hello".object_id 并点击返回 2 次不同的时间,你会得到 2 个不同的返回值,但如果你写 :hello.object_id 2 次你只会得到相同的返回值。 这应该可以解释差异。

      【讨论】:

      • 基本上冒号运算符用于分配symbol
      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        这是一个符号。基本上,您是说散列的两个元素具有键 blabloop,就像您使用字符串 "bla""bloop" 一样。但是,它们比字符串占用更少的内存,并且更容易输入。

        【讨论】:

          【解决方案8】:

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

          【讨论】:

          • 符号不可变这一事实确保它们在整个应用程序中始终是同一个实例,因此它们保证是同一个对象。检查这些参考资料:troubleshooters.com/codecorn/ruby/symbols.htmrobertsosinski.com/2009/01/11/… 如果你用谷歌搜索,你会发现更多。
          • 我说的是你对 Java 的类比。 Java 字符串与符号不同。 Java 字符串文字是但不是所有的字符串。
          • 可能我的表述不够清楚。它们之间的相似之处仅在于它们是不可变的。
          • @DhruvaSagar:如果你使用 Objective C 的NSString,这个类比会更好。 "foo" 将始终等于 "foo",因为内部相同的字符串只是被指向。不过,答案仍然令人困惑。
          【解决方案9】:

          所有这些答案都省略了一个额外的诱人细节..如果您将符号 :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 对“裸词”的回答。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-24
            • 2011-03-01
            • 1970-01-01
            • 2012-05-07
            相关资源
            最近更新 更多