Code Comments¶↑
Ruby has two types of comments: inline and block.
Inline comments start with the# character and continue until the end of the line:
# On a separate lineclassFoo# or at the end of the line# can be indenteddefbarendend
Block comments start with=begin and end with=end. Each should start on a separate line.
=beginThis iscommented out=endclassFooend=begin some_tagthis works, too=end
=begin and=end can not be indented, so this is a syntax error:
class Foo =begin Will not work =endend
Magic Comments¶↑
While comments are typically ignored by Ruby, special “magic comments” contain directives that affect how the code is interpreted.
Top-level magic comments must appear in the first comment section of a file.
NOTE: Magic comments affect only the file in which they appear; other files are unaffected.
# frozen_string_literal: truevar ='hello'var.frozen?# => true
Alternative syntax¶↑
Magic comments may consist of a single directive (as in the example above). Alternatively, multiple directives may appear on the same line if separated by “;” and wrapped between “-*-” (see Emacs’file variables).
# emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*-p'hello'.frozen?# => truep'hello'.encoding# => #<Encoding:Big5>
encoding Directive¶↑
Indicates which string encoding should be used for string literals, regexp literals and__ENCODING__:
# encoding: big5''.encoding# => #<Encoding:Big5>
Default encoding is UTF-8.
Top-level magic comments must start on the first line, or on the second line if the first line looks like#! shebang line.
The word “coding” may be used instead of “encoding”.
frozen_string_literal Directive¶↑
Indicates that string literals should be allocated once at parse time and frozen.
# frozen_string_literal: true3.timesdop'hello'.object_id# => prints same numberendp'world'.frozen?# => true
The default is false; this can be changed with--enable=frozen-string-literal. Without the directive, or with# frozen_string_literal: false, the example above would print 3 different numbers and “false”.
Starting in Ruby 3.0, string literals that are dynamic are not frozen nor reused:
# frozen_string_literal: truep"Addition: #{2 + 2}".frozen?# => false
It must appear in the first comment section of a file.
warn_indent Directive¶↑
This directive can turn on detection of bad indentation for statements that follow it:
deffooend# => no warning# warn_indent: truedefbarend# => warning: mismatched indentations at 'end' with 'def' at 6
Another way to get these warnings to show is by running Ruby with warnings (ruby -w). Using a directive to set this false will prevent these warnings to show.
shareable_constant_value Directive¶↑
Note: This directive is experimental in Ruby 3.0 and may change in future releases.
This special directive helps to create constants that hold only immutable objects, orRactor-shareable constants.
The directive can specify special treatment for values assigned to constants:
none: (default)literal: literals are implicitly frozen, others must be Ractor-shareableexperimental_everything: all made shareableexperimental_copy: copy deeply and make it shareable
Modenone (default)¶↑
No special treatment in this mode (as in Ruby 2.x): no automatic freezing and no checks.
It has always been a good idea to deep-freeze constants;Ractor makes this an even better idea as only the main ractor can access non-shareable constants:
# shareable_constant_value: noneA = {foo: []}A.frozen?# => falseRactor.new {putsA }# => can not access non-shareable objects by non-main Ractor.
Modeliteral¶↑
In “literal” mode, constants assigned to literals will be deeply-frozen:
# shareable_constant_value: literalX = [{foo: []}]# => same as [{foo: [].freeze}.freeze].freeze
Other values must be shareable:
# shareable_constant_value: literalX =Object.new# => cannot assign unshareable object to X
Note that only literals directly assigned to constants, or recursively held in such literals will be frozen:
# shareable_constant_value: literalvar = [{foo: []}]var.frozen?# => false (assignment was made to local variable)X =var# => cannot assign unshareable object to XX =Set[1,2, {foo: []}].freeze# => cannot assign unshareable object to X# (`Set[...]` is not a literal and# `{foo: []}` is an argument to `Set.[]`)
The methodModule#const_set is not affected.
Modeexperimental_everything¶↑
In this mode, all values assigned to constants are made shareable.
# shareable_constant_value: experimental_everythingFOO =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
This mode is “experimental”, because it might be error prone, for example by deep-freezing the constants of an external resource which could cause errors:
# shareable_constant_value: experimental_everythingFOO =SomeGem::Something::FOO# => deep freezes the gem's constant!
This will be revisited before Ruby 3.1 to either allow ‘everything` or to instead remove this mode.
The methodModule#const_set is not affected.
Modeexperimental_copy¶↑
In this mode, all values assigned to constants are deeply copied and made shareable. It is safer mode thanexperimental_everything.
# shareable_constant_value: experimental_copyvar = [{foo: []}]var.frozen?# => false (assignment was made to local variable)X =var# => calls `Ractor.make_shareable(var, copy: true)`var.frozen?# => falseRactor.shareable?(X)#=> truevar.object_id==X.object_id#=> false
This mode is “experimental” and has not been discussed thoroughly. This will be revisited before Ruby 3.1 to either allow ‘copy` or to instead remove this mode.
The methodModule#const_set is not affected.
Scope¶↑
This directive can be used multiple times in the same file:
# shareable_constant_value: noneA = {foo: []}A.frozen?# => falseRactor.new {putsA }# => can not access non-shareable objects by non-main Ractor.# shareable_constant_value: literalB = {foo: []}B.frozen?# => trueB[:foo].frozen?# => trueC = [Object.new]# => cannot assign unshareable object to C (Ractor::IsolationError)D = [Object.new.freeze]D.frozen?# => true# shareable_constant_value: experimental_everythingE =Set[1,2,Object.new]E.frozen?# => trueE.all(&:frozen?)# => true
The directive affects only subsequent constants and only for the current scope:
moduleMod# shareable_constant_value: literalA = [1,2,3]moduleSubB = [4,5]endendC = [4,5]moduleModD = [6]endpMod::A.frozen?,Mod::Sub::B.frozen?# => true, truepC.frozen?,Mod::D.frozen?# => false, false