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 line class Foo # or at the end of the line # can be indented def bar end end
Block comments start with =begin and end with =end. Each should start on a separate line.
=begin This is commented out =end class Foo end =begin some_tag this works, too =end
=begin and =end can not be indented, so this is a syntax error:
class Foo =begin Will not work =end end
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: true var = '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? # => true p '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: true 3.times do p 'hello'.object_id # => prints same number end p '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: true p "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:
def foo end # => no warning # warn_indent: true def bar end # => 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, or Ractor-shareable constants.
The directive can specify special treatment for values assigned to constants:
-
none: (default) -
literal: literals are implicitly frozen, others must be Ractor-shareable -
experimental_everything: all made shareable -
experimental_copy: copy deeply and make it shareable
Mode none (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: none A = {foo: []} A.frozen? # => false Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
Mode literal
In “literal” mode, constants assigned to literals will be deeply-frozen:
# shareable_constant_value: literal X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze
Other values must be shareable:
# shareable_constant_value: literal X = 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: 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.[]`)
The method Module#const_set is not affected.
Mode experimental_everything
In this mode, all values assigned to constants are made shareable.
# shareable_constant_value: experimental_everything FOO = Set[1, 2, {foo: []}] # same as FOO = Ractor.make_shareable(...) # 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_everything FOO = 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 method Module#const_set is not affected.
Mode experimental_copy
In this mode, all values assigned to constants are deeply copied and made shareable. It is safer mode than 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
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 method Module#const_set is not affected.
Scope
This directive can be used multiple times in the same file:
# 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
The directive affects only subsequent constants and only for the current scope:
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