评论" frozen_string_literal:true"做?

时间:2016-06-13 21:18:02

标签: ruby string immutability ruby-2.3

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

3 个答案:

答案 0 :(得分:217)

# 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

您还可以使用一元-冻结可变(未冻结)字符串。

答案 1 :(得分:11)

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

您可以在Ruby 2.x中使用。只需在文件的第一行中添加此注释即可。

# frozen_string_literal: true
  

文件顶部的以上注释更改了静态字符串的语义   文件中的文字。静态字符串文字将被冻结,并且   总是返回相同的对象。 (动态字符串文字的语义   保持不变。)

     

这种方式有以下好处:

     

没有丑陋的后缀。   旧版Ruby没有语法错误。   我们只需要一行   每个文件。

请阅读本主题以获取更多信息。

https://bugs.ruby-lang.org/issues/8976

答案 2 :(得分:1)

通过不为同一字符串分配新空间来提高应用程序性能,从而也节省了垃圾收集工作的时间。怎么样?当冻结字符串(字符串对象)时,是在告诉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'

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

总是有很多东西要学习并且要灵活: