Ruby:注解“frozen_string_literal:真的”吗?

fivyi3re  于 2023-04-11  发布在  Ruby
关注(0)|答案(3)|浏览(158)

这是我的项目目录中的rspec binstub。

#!/usr/bin/env ruby
begin
  load File.expand_path("../spring", __FILE__)
rescue LoadError
end
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'rspec' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rspec-core", "rspec")

这是要做什么?

# frozen_string_literal: true
7qhs6swi

7qhs6swi1#

# frozen_string_literal: true是一个神奇的注解,在Ruby 2.3中第一次被支持,它告诉Ruby文件中的所有字符串文字都被隐式冻结,就像对每个字符串都调用了#freeze一样。也就是说,如果一个字符串文字在一个文件中定义了这个注解,并且你调用了一个修改它的字符串方法,比如<<,你会得到RuntimeError: can't modify frozen String
冻结字符串可以防止无意中修改字符串而导致的错误,并可能提高性能。
像任何魔术注解一样,frozen_string_literal注解必须在文件的第一个注解部分。讽刺的是,该binstub中的frozen_string_literal注解不在binstub的第一个注解部分,并且将被忽略。
在Ruby2.3中,可以使用这个神奇的注解来为冻结字符串字面量做准备,因为它是Ruby 3中的默认值。
在Ruby 2.3中,使用--enable=frozen-string-literal标志运行,而在Ruby 3中,字符串文字在所有文件中都被冻结。您可以使用# frozen_string_literal: false覆盖全局设置。
如果你想让一个字符串文字是可变的,不管全局或每个文件的设置如何,你可以在它前面加上一元运算符+(注意运算符的优先级),或者在它上面调用.dup

# frozen_string_literal: true
"".frozen?
=> true
(+"").frozen?
=> false
"".dup.frozen?
=> false

您还可以使用一元-冻结可变(未冻结)字符串。
源代码:magic_comment在ruby/ruby中定义

yuvru6vn

yuvru6vn2#

它通过不为相同的字符串分配新的空间来提高应用程序的性能,从而也节省了垃圾收集的时间。怎么做呢?当你冻结一个字符串文字(字符串对象)时,你告诉Ruby不要让你的任何程序修改字符串文字(对象)。
一些明显的观察要记住。

1.通过冻结字符串字面量,您不会为它分配新的内存空间。

示例:

无魔法注解为同一字符串分配新空间(观察打印的不同对象ID)

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358500

*魔法注解ruby只分配一次空间 *

# frozen_string_literal: true

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358640

2.通过冻结字符串字面量,程序将在尝试修改字符串字面量时引发异常。

示例:

不带魔法注解,可以修改字符串文字。

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

使用魔法注解,修改字符串文字时会引发异常

# frozen_string_literal: true

name = 'john'
name << ' cash'  #=> `<main>': can't modify frozen String (FrozenError)

puts name

总有更多的东西需要学习和灵活:

r55awzrz

r55awzrz3#

在Ruby3.0中,Matz(Ruby的创建者)决定在默认情况下冻结所有String文字。

编辑2019:他决定放弃在Ruby 3.0中将frozen-string-literals设为默认值的想法(源代码:https://bugs.ruby-lang.org/issues/11473#note-53)

你可以在Ruby 2.x中使用。只要在文件的第一行添加这个注解。

# frozen_string_literal: true

文件顶部的上述注解更改了文件中静态字符串文字的语义。静态字符串文字将被冻结并始终返回相同的对象。(动态字符串文字的语义不会更改。)
这种方式具有以下优点:
没有丑陋的f后缀。没有旧版Ruby的语法错误。我们只需要每个文件一行。
请阅读此主题以获取更多信息。
https://bugs.ruby-lang.org/issues/8976

相关问题