зеркало из https://github.com/github/ruby.git
254 строки
7.3 KiB
Plaintext
254 строки
7.3 KiB
Plaintext
= 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
|