1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
= Code Comments
Ruby has two types of comments: inline and block.
Inline comments start with the <code>#</code> 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 <code>=begin</code> and end with <code>=end</code>.
Each should start on a separate line.
=begin
This is
commented out
=end
class Foo
end
=begin some_tag
this works, too
=end
<code>=begin</code> and <code>=end</code> 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}[https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html]).
# 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 <code>__ENCODING__</code>:
# 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 <tt>#! shebang line</tt>.
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 <code>--enable=frozen-string-literal</code>.
Without the directive, or with <code># frozen_string_literal: false</code>,
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 (<code>ruby -w</code>). 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}[rdoc-ref:Ractor@Shareable+and+unshareable+objects] 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_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_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
|