评估冻结的字符串

saw*_*awa 8 ruby string immutability literals

我的模糊理解是,使用Ruby 2.2的frozen字符串或Ruby 2.3的frozen-string-literal: truepragma方法,相关的冻结字符串文字在整个程序执行过程中只评估一次,当且仅当字符串没有插值时.以下似乎说明了这一点:

没有内插

#frozen-string-literal: true
5.times{p "".object_id}
Run Code Online (Sandbox Code Playgroud)

输出(相同的对象ID):

70108065381260
70108065381260
70108065381260
70108065381260
70108065381260
Run Code Online (Sandbox Code Playgroud)

内插

#frozen-string-literal: true
5.times{p "#{}".object_id}
Run Code Online (Sandbox Code Playgroud)

输出(不同的对象ID):

70108066220720
70108066220600
70108066220420
70108066220300
70108066220180
Run Code Online (Sandbox Code Playgroud)
  1. 这个属性是什么(即仅被评估一次)被称为?它应该与不变性不同.
  2. 当字符串具有这样的属性时,我对条件的理解是否正确?提到这个的官方文件在哪里?
  3. 有没有办法让插值字符串只被评估一次?

ndn*_*kov 7

  1. 实习.据说这些字符串是实习的.
  2. 不完全的.更像是解释器在评估之前可以决定字符串的值.例如,考虑:

    5.times { puts "#{'foo'}".object_id }
    
    Run Code Online (Sandbox Code Playgroud)

    即使涉及插值,id也是相同的.

  3. 不.这是内部优化.主要观点Object#freeze是不变性.


更新:只有文字字符串被内化.这在这里很明显.

我找不到负责插值的代码部分.所以我不确定为什么"#{'foo'}"被认为是文字字符串.请注意,无论何处发生此转换,它都处于较低的解析器级别,并且在任何实际处理之前发生.这是String#freeze映射到的事实rb_str_freeze,而不是调用opt_str_freeze.