ruby 评论“frozen_string_literal: true”有什么作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37799296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:49:53  来源:igfitidea点击:

What does the comment "frozen_string_literal: true" do?

rubystringimmutabilityruby-2.3

提问by messanjah

This is the rspecbinstub in my project directory.

这是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")

What is this intended to do?

这是要做什么?

# frozen_string_literal: true

回答by Dave Schweisguth

# frozen_string_literal: trueis a magic comment, supported for the first time in Ruby 2.3, that tells Ruby that all string literals in the file are implicitly frozen, as if #freezehad been called on each of them. That is, if a string literal is defined in a file with this comment, and you call a method on that string which modifies it, such as <<, you'll get RuntimeError: can't modify frozen String.

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

The comment must be on the first line of the file.

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

In Ruby 2.3, you can use this magic comment to prepare for frozen string literals being the default in Ruby 3.

在 Ruby 2.3 中,您可以使用这个神奇的注释来准备冻结字符串文字,这是 Ruby 3 中的默认值

In Ruby 2.3 run with the --enable=frozen-string-literalflag, and in Ruby 3, string literals are frozen in all files. You can override the global setting with # frozen_string_literal: false.

在 Ruby 2.3 中使用该--enable=frozen-string-literal标志运行,而在 Ruby 3 中,所有文件中的字符串文字都被冻结。您可以使用 覆盖全局设置# frozen_string_literal: false

If you want a string literal to be mutable regardless of the global or per-file setting, you can prefix it with the unary +operator (being careful with operator precedence) or call .dupon it:

如果您希望字符串文字无论全局或每个文件设置如何都是可变的,您可以使用一元运算+符作为前缀(注意运算符优先级)或调用.dup它:

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

You can also freeze a mutable (unfrozen) string with unary -.

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

回答by imechemi

It improves application performance by not allocating new space for the same string, thereby also saving time for garbage collection chores. How? when you freeze a string literal(string object), you're telling Ruby to not let any of your programs modify the string literal (object).

它通过不为同一字符串分配新空间来提高应用程序性能,从而也节省了垃圾收集杂务的时间。如何?当您冻结字符串文字(字符串对象)时,您是在告诉 Ruby 不要让您的任何程序修改字符串文字(对象)。

Some obvious observations to keep in mind.

要记住一些明显的观察结果。

1. By freezing string literals, you're not allocating new memory space for it.

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

Example:

例子:

Without magic commentallocates new space for the same string (Observe the different object IDs printed)

没有魔法注释会为同一个字符串分配新的空间(观察打印的不同对象 ID)

def hello_id
  a = 'hello'
  a.object_id
end

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

With magic comment, ruby allocates space only once

使用魔术注释,ruby 只分配一次空间

# frozen_string_literal: true

def hello_id
  a = 'hello'
  a.object_id
end

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


2. By freezing string literals, your program will raise an exception when trying to modify the string literal.

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

Example:

例子:

Without magic comment, you can modify the string literals.

没有魔术注释,您可以修改字符串文字。

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

With magic comment, an exception will be raised when you modify string literals

使用魔术注释,当您修改字符串文字时将引发异常

# frozen_string_literal: true

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

puts name      

There's always more to learn and be flexible:

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

回答by Alexandr

In Ruby 3.0. Matz (Ruby's creator) decided to make all String literals frozen by default.

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

You can use in Ruby 2.x. Just add this comment in the first line of your files.

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

# frozen_string_literal: true

The above comment at top of a file changes semantics of static string literals in the file. The static string literals will be frozen and always returns same object. (The semantics of dynamic string literals is not changed.)

This way has following benefits:

No ugly f-suffix. No syntax error on older Ruby. We need only a line for each file.

文件顶部的上述注释更改了文件中静态字符串文字的语义。静态字符串文字将被冻结并始终返回相同的对象。(动态字符串文字的语义没有改变。)

这种方式有以下好处:

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

Plese, read this topic for more information.

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

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

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