Комментарии к коду
В 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 line.
Вместо «encoding» можно использовать слово «coding».
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 и может быть изменена в будущих выпусках.
Эта специальная директива помогает создавать константы, которые содержат только неизменяемые объекты или объекты, доступные для ракторов.
Директива может указать специальное обращение к значениям, присвоенным константам:
-
none: (по умолчанию) -
literal: литералы неявным образом замораживаются, другие должны быть доступны для ракторов -
experimental_everything: все значения становятся доступными для ракторов -
experimental_copy: глубокая копия и доступность для ракторов
Режим none (по умолчанию)
В этом режиме нет специального обращения (как в Ruby 2.x): нет автоматического замораживания и нет проверок.
Всегда было хорошей идеей глубоко замораживать константы; 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, чтобы либо разрешить «все», либо вместо этого удалить этот режим.
Метод Module#const_set не затрагивается.
Режим experimental_copy
В этом режиме все значения, присвоенные константам, глубоко копируются и становятся доступными для ракторов. Это более безопасный режим, чем experimental_everything.
# shareable_constant_value: experimental_everything
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
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.