代码注释¶ ↑
Ruby 有两种类型的注释:行内注释和块注释。
行内注释以 #
字符开始,并持续到行尾
# On a separate line class Foo # or at the end of the line # can be indented def bar end end
块注释以 =begin
开始,以 =end
结束。每一对都应在单独的行上开始。
=begin This is commented out =end class Foo end =begin some_tag this works, too =end
=begin
和 =end
不能缩进,否则会出现语法错误
class Foo =begin Will not work =end end
魔法注释¶ ↑
虽然注释通常会被 Ruby 忽略,但特殊的“魔法注释”包含影响代码解释方式的指令。
顶层魔法注释必须出现在文件的第一个注释部分中。
注意:魔法注释仅影响它们出现的那个文件;其他文件不受影响。
# frozen_string_literal: true var = 'hello' var.frozen? # => true
替代语法¶ ↑
魔法注释可以包含单个指令(如上面的示例)。或者,如果多个指令用 “;” 分隔并用 “-*-” 包裹(参见 Emacs 的 文件变量),则可以出现在同一行上。
# emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*- p 'hello'.frozen? # => true p 'hello'.encoding # => #<Encoding:Big5>
encoding
指令¶ ↑
指示字符串字面量、正则表达式字面量和 __ENCODING__
应使用的字符串编码
# encoding: big5 ''.encoding # => #<Encoding:Big5>
默认编码为 UTF-8。
顶层魔法注释必须从第一行开始,如果第一行看起来像 ! shebang 行,则从第二行开始。
可以使用 “coding” 而不是 “encoding”。
frozen_string_literal
指令¶ ↑
指示字符串字面量应在解析时分配一次并冻结。
# frozen_string_literal: true 3.times do p 'hello'.object_id # => prints same number end p 'world'.frozen? # => true
默认值为 false;可以使用 --enable=frozen-string-literal
更改。如果没有该指令,或者使用 frozen_string_literal: false,则上面的示例将打印 3 个不同的数字和 “false”。
从 Ruby 3.0 开始,动态的字符串字面量不会被冻结或重用
# frozen_string_literal: true p "Addition: #{2 + 2}".frozen? # => false
它必须出现在文件的第一个注释部分中。
warn_indent
指令¶ ↑
此指令可以为紧随其后的语句启用错误缩进检测
def foo end # => no warning # warn_indent: true def bar end # => warning: mismatched indentations at 'end' with 'def' at 6
另一种显示这些警告的方式是以警告模式运行 Ruby (ruby -w
)。使用指令将此设置为 false 将阻止显示这些警告。
shareable_constant_value
指令¶ ↑
注意:此指令在 Ruby 3.0 中是实验性的,并且可能在未来的版本中更改。
此特殊指令有助于创建仅保存不可变对象或 Ractor 可共享 常量的常量。
该指令可以指定分配给常量的值的特殊处理
-
none
: (默认) -
literal
: 字面量被隐式冻结,其他值必须是 Ractor 可共享的 -
experimental_everything
: 全部设为可共享 -
experimental_copy
: 深度复制并使其可共享
模式 none
(默认)¶ ↑
此模式下没有特殊处理(与 Ruby 2.x 中相同):没有自动冻结,也没有检查。
深度冻结常量一直是一个好主意;Ractor
使其成为一个更好的主意,因为只有主 ractor 才能访问不可共享的常量
# shareable_constant_value: none A = {foo: []} A.frozen? # => false Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
模式 literal
¶ ↑
在 “literal” 模式下,分配给字面量的常量将被深度冻结
# shareable_constant_value: literal X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze
其他值必须是可共享的
# shareable_constant_value: literal X = Object.new # => cannot assign unshareable object to X
请注意,只有直接分配给常量或递归保存在此类字面量中的字面量才会被冻结
# shareable_constant_value: literal var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => cannot assign unshareable object to X X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X # (`Set[...]` is not a literal and # `{foo: []}` is an argument to `Set.[]`)
方法 Module#const_set
不受影响。
模式 experimental_everything
¶ ↑
在此模式下,分配给常量的所有值都将设为可共享。
# shareable_constant_value: experimental_everything FOO = Set[1, 2, {foo: []}] # same as FOO = Ractor.make_sharable(...) # OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze` var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => calls `Ractor.make_shareable(var)` var.frozen? # => true
此模式是“实验性的”,因为它可能会容易出错,例如,深度冻结外部资源的常量可能会导致错误
# shareable_constant_value: experimental_everything FOO = SomeGem::Something::FOO # => deep freezes the gem's constant!
这将在 Ruby 3.1 之前重新审视,以允许 ‘everything’ 或改为删除此模式。
方法 Module#const_set
不受影响。
模式 experimental_copy
¶ ↑
在此模式下,分配给常量的所有值都将被深度复制并使其可共享。它比 experimental_everything
模式更安全。
# shareable_constant_value: experimental_copy var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => calls `Ractor.make_shareable(var, copy: true)` var.frozen? # => false Ractor.shareable?(X) #=> true var.object_id == X.object_id #=> false
此模式是“实验性的”,尚未经过充分讨论。这将在 Ruby 3.1 之前重新审视,以允许 ‘copy’ 或改为删除此模式。
方法 Module#const_set
不受影响。
作用域¶ ↑
此指令可以在同一文件中多次使用
# shareable_constant_value: none A = {foo: []} A.frozen? # => false Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor. # shareable_constant_value: literal B = {foo: []} B.frozen? # => true B[:foo].frozen? # => true C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError) D = [Object.new.freeze] D.frozen? # => true # shareable_constant_value: experimental_everything E = Set[1, 2, Object.new] E.frozen? # => true E.all(&:frozen?) # => true
该指令仅影响后续常量,并且仅影响当前作用域
module Mod # shareable_constant_value: literal A = [1, 2, 3] module Sub B = [4, 5] end end C = [4, 5] module Mod D = [6] end p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true p C.frozen?, Mod::D.frozen? # => false, false