这是我的项目目录下的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

当前回答

它通过不为相同的字符串分配新空间来提高应用程序性能,从而也节省了垃圾收集的时间。怎么做?当你冻结一个字符串字面值(string object)时,你是在告诉Ruby不要让你的任何程序修改字符串字面值(object)。

要记住一些显而易见的观察结果。

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

例子:

注释为相同的字符串分配新的空间 (观察打印的不同对象id)

def hello_id
  a = 'hello'
  a.object_id
end

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

使用magic comment, 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

使用magic comment,在修改字符串字面量时将引发异常

# frozen_string_literal: true

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

puts name      

总是有更多的东西要学,要灵活:

https://bugs.ruby-lang.org/issues/8976 https://www.mikeperham.com/2018/02/28/ruby-optimization-with-one-magic-comment/

其他回答

在Ruby 3.0中。Matz (Ruby的创造者)决定默认冻结所有String文字。

编辑2019:他决定放弃Ruby 3.0默认的冻结字符串文字的想法(来源: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

它通过不为相同的字符串分配新空间来提高应用程序性能,从而也节省了垃圾收集的时间。怎么做?当你冻结一个字符串字面值(string object)时,你是在告诉Ruby不要让你的任何程序修改字符串字面值(object)。

要记住一些显而易见的观察结果。

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

例子:

注释为相同的字符串分配新的空间 (观察打印的不同对象id)

def hello_id
  a = 'hello'
  a.object_id
end

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

使用magic comment, 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

使用magic comment,在修改字符串字面量时将引发异常

# frozen_string_literal: true

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

puts name      

总是有更多的东西要学,要灵活:

https://bugs.ruby-lang.org/issues/8976 https://www.mikeperham.com/2018/02/28/ruby-optimization-with-one-magic-comment/

# frozen_string_literal: true是一个神奇的注释,在Ruby 2.3中首次支持,它告诉Ruby文件中的所有字符串文字都被隐式冻结,就像对每个字符串都调用了#freeze一样。也就是说,如果在文件中使用此注释定义了一个字符串字面值,并且您调用该字符串上的一个方法来修改它,例如<<,您将得到RuntimeError: can't modify frozen string。

注释必须在文件的第一行上。

在Ruby 2.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

你也可以用unary -冻结一个可变的(未冻结的)字符串。

来源:在ruby/ruby中定义的magic_comment