Spec-Zone.ru › Ruby 3.2

Комментарии к коду

В 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API