ruby - Ruby 符号是否存在是因为字符串是可变的而不是 interned 的?

标签 ruby

我已经使用 Ruby 大约一年了,有一个语言问题:符号是必需的吗,因为 Ruby 字符串是可变的而不是固定的?

例如,在 Java 中,字符串是不可变的并且是固定的。所以“foo”在值(value)和引用上总是等于“foo”,并且它的值(value)不能改变。在 Ruby 中,字符串是可变的而不是固定的,因此 "a".object_id == "a".object_id 将为 false。

如果 Ruby 像 Java 一样实现了字符串,就不需要符号了,对吧?

最佳答案

从 Ruby 2.3 开始,不可变的 String 可以通过 RUBYOPT 标记 --enable-frozen-string-literals 实现 即

RUBYOPT=--enable-frozen-string-literals ruby /some/file

这将导致所有 String 文字(使用 ""%q{}%Q{} 创建的字符串 或“#{}”样式)变得不可变。此功能当前被视为 Ruby 3.0 的默认功能。 Follow along with Feature#11473 .此功能也可在文件级别而不是全局级别作为“魔术评论”使用

# frozen_string_literal: true

这将与 RUBYOPT 版本产生相同的影响,但仅适用于特定文件。 (另一种方法是直接与 VM 交互 RubyVM::InstructionSequence.compile_option = {frozen_string_literal: true})

因为这是可选的,显然它可以打开和关闭,并且在 3.0 中仍然是一个选项,只是默认为打开而不是关闭。可变的 String 仍然可以使用 String.new 创建,不可变的 String 可以被 dup 来创建它们dup 计数器部分可变。 (请注意上面:由于 "",插值 "#{}" 也会创建一个新的不可变字符串)

尽管如此,它并不能取代 ruby​​ 中对 Symbols 的需求。首先,为 ruby​​ 提供支持的底层 C 通过 rb_itern 大量利用 Symbols 来处理方法定义之类的引用(这些被命名为 "Immortal Symbols" 并且永远不会被 GC)。

此外,Symbols 就像 ruby​​ 中的所有东西一样,都是它们自己的 Object 并且有它们自己有用的功能集。以 Symbol#to_proc 为例。这起源于语法简化的猴子补丁解决方案,并在 1.8.7 中被纳入核心。这种风格受到整个 ruby​​ 社区的高度鼓励和经常利用。请告知您如何建议使用 String 而不是 Symbol 来降低此功能。

虽然 Symbols 过去常常被认为有些“危险”(因为缺少更好的词),因为它们的拘禁和内存消耗与 ruby​​ 的动态相结合。从 Ruby 2.2 开始,大多数 Symbols(见上文)都可以被垃圾收集,即通过 String internment 在 ruby​​ 内部创建的符号(#intern#to_sym 等)。 (这些被创造为“凡人的象征”)

次要注意事项包括

 define_method(param[:meth].to_sym) {}

这似乎是因为它正在调用 to_sym 它应该是一个 “凡人符号” 但是因为 define_method 调用 rb_intern 为了保留方法引用,它实际上会创建一个“不朽符号”

希望这篇文章有助于解释 Symbol 在 ruby​​ 中的必要性,不仅从开发人员的角度,而且作为 ruby​​ 实现的 C 内部的一部分的大量使用。

关于ruby - Ruby 符号是否存在是因为字符串是可变的而不是 interned 的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44634073/

相关文章:

ruby-on-rails - 在 Rails 中安排 ActiveJob

ruby-on-rails - 注册并同时创建新对象

ruby - 如何在 Ruby 中一次读取一个文件字节?

ruby-on-rails - 为什么 Rails 2.3 不生成 Gemfile?

ruby-on-rails - 根据来自另一个模型(rails)的信息限制对模型的所有访问

ruby - 从 Sinatra 内部调用 Sinatra

ruby-on-rails - Rails 指南第 5.12 节的 UrlGenerationError

ruby - 在 Windows 8 : Unable to execute file C:\Program Files(x86)\Heroku\ruby-1. 9.3\bin\gem.bat 上安装 heroku toolbelt 时出错

ruby - 如何在 Ruby Net :HTTP? 中处理多部分 http 响应

Ruby:如何从类方法设置实例变量?