Подтвердить что ты не робот

Что делает комментарий "frozen_string_literal: true"?

Это rspec binstub в моей директории проекта.

#!/usr/bin/env ruby
begin
  load File.expand_path("../spring", __FILE__)
rescue LoadError
end
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'rspec' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rspec-core", "rspec")

Что это значит?

# frozen_string_literal: true
4b9b3361

Ответ 1

# frozen_string_literal: true - магический комментарий, впервые поддерживаемый в Ruby 2.3, который сообщает Ruby, что все строковые литералы в файле неявно заморожены, как если бы для каждого из них был вызван #freeze. То есть, если строковый литерал определен в файле с этим комментарием, и вы вызываете метод для этой строки, который его модифицирует, например <<, вы получите RuntimeError: can't modify frozen String.

Комментарий должен быть в первой строке файла.

В Ruby 2.3 этот магический комментарий можно использовать для подготовки к фиксированным строковым литералам, которые по умолчанию используются в Ruby 3.

В Ruby 2.3 запускается с --enable=frozen-string-literal, а в Ruby 3 строковые литералы фиксируются во всех файлах. Вы можете переопределить глобальную настройку с помощью # frozen_string_literal: false.

Если вы хотите, чтобы строковый литерал был изменяемым независимо от глобальных или файловых настроек, вы можете поставить .dup ним префикс унарным оператором + (осторожно с приоритетом оператора) или вызвать .dup для него:

# frozen_string_literal: true
"".frozen?
=> true
(+"").frozen?
=> false
"".dup.frozen?
=> false

Вы также можете заморозить изменяемую (незамерзающую) строку с помощью unary -.

Ответ 2

В Ruby 3.0. Матц (создатель Rubys) решил сделать все строковые литералы замороженными по умолчанию.

Вы можете использовать в Ruby 2.x. Просто добавьте этот комментарий в первую строку ваших файлов.

# frozen_string_literal: true

Приведенный выше комментарий вверху файла меняет семантику статических строковых литералов в файле. Статические строковые литералы будут заморожены и всегда будут возвращать один и тот же объект. (Семантика динамических строковых литералов не изменяется.)

Этот способ имеет следующие преимущества:

Нет уродливого f-суффикса. Нет ошибки синтаксиса на старых Ruby. Нам нужна только строка для каждого файла.

Пожалуйста, прочитайте эту тему для получения дополнительной информации.

https://bugs.ruby-lang.org/issues/8976

Ответ 3

Это повышает производительность приложения, не выделяя новое пространство для той же строки, тем самым экономя время на сборку мусора. Как? когда вы замораживаете строковый литерал (строковый объект), вы говорите Ruby, чтобы ни одна из ваших программ не изменяла строковый литерал (объект).

Несколько очевидных наблюдений, которые нужно иметь в виду.

1. Замораживая строковые литералы, вы не выделяете для этого новое пространство памяти.

Пример:

Без магического комментария выделяется новое место для той же строки (обратите внимание на разные идентификаторы объекта)

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358500

С магическим комментарием, рубин выделяет место только один раз

# frozen_string_literal: true

def hello_id
  a = 'hello'
  a.object_id
end

puts hello_id   #=> 70244568358640
puts hello_id   #=> 70244568358640

2. Замораживая строковые литералы, ваша программа вызовет исключение при попытке изменить строковый литерал.

Пример:

Без магического комментария вы можете изменить строковые литералы.

name = 'Johny'
name << ' Cash'

puts name     #=> Johny Cash

С волшебным комментарием, будет возникать исключение, когда вы изменяете строковые литералы

# frozen_string_literal: true

name = 'john'
name << ' cash'

puts name      #=> '<main>': can't modify frozen String (FrozenError)

Всегда есть чему поучиться и быть гибким: