ruby - Ruby gsub 然后冻结获取不同的 object_id
问题描述
我做了一个关于红宝石冻结的实验:
# example1
a = 'a'.freeze
puts "--Identical object_id--"
puts a.object_id
puts 'a'.freeze.object_id
# example 2
b = 'a'.gsub('a', 'b').freeze
another_b = 'a'.gsub('a', 'b').freeze
puts "--Got three different object_id--"
puts 'b'.freeze.object_id
puts b.object_id
puts another_b.object_id
b.frozen? #=> true
b和another_b是冻结字符串'b',为什么它们有不同的object_id?
解决方案
Ruby (YARV) 识别冻结的字符串文字并创建优化的指令序列:
$ ruby --dump=insns -e '"a".freeze'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,3)>==============================
0000 opt_str_freeze "a" ( 1)[Li]
0002 leave
与非冻结字符串相反:
$ ruby --dump=insns -e '"a"'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,3)>==============================
0000 putstring "a" ( 1)[Li]
0002 leave
以这种方式优化的字符串将引用相同的对象,即它们具有相同的object_id
. 但它只适用于字符串文字,即"...".freeze
。freeze
通过send(:freeze)
或调用带有freeze
插值的字符串或非文字(如变量)或方法调用的结果会导致普通方法调用:
$ ruby --dump=insns -e '"a".to_s.freeze'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,15)>=============================
0000 putstring "a" ( 1)[Li]
0002 opt_send_without_block <callinfo!mid:to_s, argc:0, ARGS_SIMPLE>, <callcache>
0005 opt_send_without_block <callinfo!mid:freeze, argc:0, ARGS_SIMPLE>, <callcache>
0008 leave
以这种方式冻结的字符串将是具有不同object_id
.
请注意,所有这些都是特定于实现的。您不应该依赖这些优化。
推荐阅读
- r - 如何在每个会话中仅显示一次警告?
- reactjs - 设计模式:以何种方式在 DB 中构建表:将网站上的文章的访问权限限制为仅订阅用户?
- apache-kafka - 从命令提示符启动 Kafka 消费者时,我收到 Class Not Found Exception。我该如何解决这个问题?
- javascript - Vuejs在下拉列表中获取数组下的数组
- javascript - Jquery datepicker beforeShowDay 仍然可以点击,即使所有天都应该已经不可选择
- groovy - 我想要一个自定义 JQL 函数来为 Jira 中的 nfeed 字段创建子查询(通过Adaptavist scriptrunner)。有任何想法吗?
- python - 如何按元素组合两个列表列表?
- node.js - 访问端点 URL 时浏览器发出什么 HTTP 请求?
- python - PyTorch CNN 教程的混淆矩阵和测试精度
- angular - Angular 9 - HttpInterceptor - 无法读取 null 的属性长度