【问题标题】:When to use symbols in Ruby [duplicate]何时在 Ruby 中使用符号 [重复]
【发布时间】:2014-09-09 22:17:45
【问题描述】:

我不清楚符号的价值和正确使用。

好处似乎是它们消除了对相同哈希的多个副本的需要,因为它只存在于内存中。我想知道这是否属实,以及这会带来什么其他好处。

如果我创建一个具有nameemailpassword 等属性的用户对象,并为每个属性使用符号而不是字符串,这是否意味着每个属性只有一个对象?看起来这样可以避免哈希中属性的字符串副本(这似乎是一件好事)。

有人能帮我理解什么是符号,什么时候最好在哈希中的字符串上使用符号?各有什么好处和弊端?

另外,谁能谈谈每个人的内存权衡?由于可扩展性很重要,我很好奇符号是否有助于提高速度。

【问题讨论】:

  • 太棒了,谢谢。你知道相对的内存权衡吗?我可以说创建的对象更少,我认为这通常会更好。但我也对实际的性能体验或对实际权衡的更多见解感到好奇。
  • 我不明白你为什么提到哈希。哈希是否与您的问题相关?而且我不知道您所说的“需要相同哈希的多个副本”是什么意思。
  • 就像我说的,我是 ruby​​ 的新手,所以也许我没有像以前那样清楚。我提到了哈希,因为到目前为止我看到的主要领域是符号被用作哈希中重复使用的字符串的替代品。
  • 第二个链接比我发布的第一个链接要好得多,它们两个结合起来应该可以形成你的答案。如果还有什么不清楚的,请告诉我,我会尽力解答。

标签: ruby symbols


【解决方案1】:

除了避免重复分配内存的需要之外,符号的相等性比较比字符串快,并且它们的哈希码的计算速度比字符串快(因此,从Hash 存储和检索数据在使用符号而不是而不是使用字符串键)。

在内部,Ruby 使用与符号密切相关的东西来标识方法、类的名称等。因此,例如,当您检索对象支持的方法列表(使用obj.methods)时,您会得到一个符号数组。当您想“动态地”调用方法时,使用存储在变量中或作为参数传入的名称,您必须使用符号。同样用于获取/设置实例变量、常量等的值。

直觉上,你可以这样想。如果你曾经用 C 编程过,你写过这样的东西:

 #define SOMETHING 1
 #define SOMETHING_ELSE 2

这些defines 消除了在您的代码中使用“幻数”的需要。使用的名称(SOMETHING 等)与程序的用户无关,就像函数或类的名称与用户无关一样。它们只是代码内部的“标签”,只与程序员有关。符号在 Ruby 程序中扮演着类似的角色。它们是一种具有类似于整数的性能属性的数据类型,但具有文字语法,这使得它们对人类程序员来说是有意义的名称。

一旦你“理解”了 Ruby 符号的概念,如果你曾经用 Lisp 编程,理解 Lisp 符号就会容易得多。在 Lisp 中,符号是构成程序代码的基本数据类型。 (因为 Lisp 程序是数据,可以这样操作。)

【讨论】:

    【解决方案2】:

    符号或“内部”(也称为“内部”)对于散列键、公共参数和其他具有相同值的重复字符串的开销低效的地方非常有用。

    例如:

    params[:name]
    my_function(with: { arguments: [ ... ] })
    record.state = :completed
    

    这些通常比字符串更可取,因为它们会经常重复

    最常见的用途是:

    • 哈希键
    • 方法的参数
    • 选项标志或枚举类型属性值

    在处理未知组成的用户数据时,最好使用字符串。与可以被垃圾回收的字符串不同,符号是永久性的。将任意用户数据转换为符号可能会用垃圾填满符号表,如果有人恶意,您的应用程序可能会崩溃。

    例如:

    user_data = JSON.load(...).symbolize_keys
    

    这将允许攻击者创建带有故意长的随机名称的 JSON 数据,到时会用各种无用的垃圾使您的进程膨胀。

    【讨论】:

    • 安全点拿捏得当;绝对是我会记住的。澄清一下:我基本上不想使用符号来指代可能会发生变化的数据,对吧?
    • 符号几乎从不用于存储“数据”,尽管它们可能像 enum 一样被使用。无缘无故地符号化字符串数据通常会适得其反。
    • 明白了;所以实际使用可能类似于为每个用户分配一个对象的内部引用?到目前为止,这似乎是(模糊地)我见过的唯一实际用例。你能帮我更好地理解吗?
    【解决方案3】:

    是的,你的例子很好。

    姓名、电子邮件和密码都可以存储为符号,即使在哈希中 - 特定对象仍然可以是字符串对象。

    {
      :name => 'John doe',
      :email => 'foo@hotmail.com',
      :password => 'lassdgjkl23853'
    }
    

    【讨论】:

    • 谢谢! :) 我想我更多的是符号的适当用例,而不是它们是否可以存储在哈希中。也许我的问题没有我希望的那么清楚
    【解决方案4】:

    您应该考虑像数字这样的符号。它是在第一次使用时创建的常量、不可变和非 gc 对象,您应该在需要引用无法复制的对象时使用它们,例如:

    • 消息又名方法(Ruby 没有重载)
    • 哈希键(Ruby 没有多重哈希)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-20
      • 2013-05-13
      • 2016-04-30
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多