Ruby符号是否存在,因为字符串是可变的而不是实体的?

Ste*_*ter 3 ruby

我已经在Ruby工作了大约一年了,并且有一个语言问题:因为Ruby字符串是可变的而不是实习,所以它们是必需的符号吗?

在Java中,字符串是不可变的和实体的.所以"foo"在值和引用中总是等于"foo",它的值不能改变.在Ruby中,字符串是可变的而不是实体,因此"a".object_id == "a".object_id将是错误的.

如果Ruby实现了像Java这样的字符串,那么符号就没有必要了,对吧?

eng*_*nky 5

从Ruby 2.3开始,不可变的Strings已经可选地通过RUBYOPT标志--enable-frozen-string-literals ie实现

RUBYOPT=--enable-frozen-string-literals ruby /some/file
Run Code Online (Sandbox Code Playgroud)

这将导致所有String文字(使用创建的字符串"",%q{},%Q{},或"#{}"样式),成为不可改变的.此功能目前被认为是Ruby 3.0的默认功能.按照功能#11473进行操作.此功能在文件级别而非全局级别上也可用作"魔术评论"

# frozen_string_literal: true
Run Code Online (Sandbox Code Playgroud)

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

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

所有这一切都没有取代Symbols红宝石的需要.首先,Cruby利用Symbols大量的权力rb_itern来处理类似方法定义的引用(这些被称为"不朽的符号",永远不会被GC).

此外,Symbols像ruby中的所有东西都是他们自己的东西,Object并拥有自己有用的功能集.以Symbol#to_proc为例.这起源于猴子补丁解决方案的语法简易性,并在1.8.7中被用于核心.这种风格受到红宝石社区的高度鼓励和定期利用.请告知您如何建议降低此功能使用String而不是Symbol.

虽然Symbols过去被认为有点"危险"(由于缺乏一个更好的词)由于与红宝石的动态组合,他们的拘禁和内存消耗.如红宝石2.2的最Symbols(见上文)可通过红宝石的内部产生垃圾收集即符号String拘禁(#intern,#to_sym等).(这些已被创造出"凡人符号")

小问题包括类似的事情

 define_method(param[:meth].to_sym) {}
Run Code Online (Sandbox Code Playgroud)

这似乎是因为它调用to_sym它应该是一个"凡人符号",但由于define_method调用rb_intern保持方法引用它实际上将创建一个"不朽的符号"

希望这种向下运行有助于解释Symbolruby 的必要性,不仅从开发人员的角度来看,还有大量使用作为Cruby实现内部的一部分.


Jas*_* FB 2

差不多,是的。我的理解是编译器保留一个符号表,该表可以动态增长。这就是为什么您绝不能接受用户输入并将其未经检查地转换为符号,因为您可以创建所谓的符号溢出攻击

我相信 Ruby 2.2 中已经修复了符号溢出漏洞。

请参阅收到警告:拒绝服务

  • 对于现代 Ruby,这不再像以前那样是一个问题(也就是说,创建符号现在与任何其他对象一样昂贵)。Ruby 的早期版本将现有符号无限期地保留在内存中。然而,从 Ruby 2.2 开始,符号也将被垃圾收集,类似于(几乎)任何其他对象。 (3认同)