Мы легко можем найти такой стиль во многих известных репозиториях, таких как стойка, рельсы и т. Д.
PATH_INFO = 'PATH_INFO'.freeze
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
SCRIPT_NAME = 'SCRIPT_NAME'.freeze
QUERY_STRING = 'QUERY_STRING'.freeze
CACHE_CONTROL = 'Cache-Control'.freeze
CONTENT_LENGTH = 'Content-Length'.freeze
CONTENT_TYPE = 'Content-Type'.freeze
HTTP_IF_MODIFIED_SINCE = 'HTTP_IF_MODIFIED_SINCE'.freeze
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
Интересно, почему эти постоянные строки заморожены. Поскольку все они являются константами, должен быть только один экземпляр. Конечно, мы можем поместить "foo".freeze
где-нибудь для ссылки на тот же экземпляр синглтона, однако люди обычно вместо этого пишут буквальное имя переменной, например HTTP_IF_MODIFIED_SINCE
.
Так что, на мой взгляд, это не имеет никакого значения, несмотря на использование #freeze
, так почему люди замораживают константы?
3 ответа
Это правильно, что Ruby выводит предупреждение, когда вы повторно присваиваете значение уже инициализированной константе:
> FOO = 'foo'
> FOO = 'bar'
# :2: warning: already initialized constant FOO
# :1: warning: previous definition of FOO was here
> FOO
# => "bar"
Но нет защиты от изменения значения в константе. Пример без freeze
:
> FOO = 'foo'
> FOO[1] = '-'
> FOO
# => "f-o"
Но freeze
позволяет защитить значение констант от изменения. Пример с freeze
:
> FOO = 'foo'.freeze
> FOO[1] = '-'
# => RuntimeError: can't modify frozen String
String#freeze
, но забываю первоначальное намерение #freeze
...Orz
String#freeze
Обычно Rubyist замораживает строковые литералы, чтобы ускорить выполнение. Если есть вызов какой-либо функции, например, как показано ниже, в каком-либо контроллере, каждый запрос будет вызывать эту функцию.
log("debug")
Происходит то, что ruby каждый раз определяет новый объект строки мусора. Размещение объекта платное. он потребляет память и процессор. Мусор будет там, пока GC не соберет их.
Но если литералы заморожены
log("debug".freeze)
Ruby выделяет один раз и кэширует его для дальнейшего использования. Кроме того, строковый объект будет неизменным и безопасным для использования в многопоточной среде.
От рубина 3.0 рубин заморозит каждую струну, - считает Мац.
обновление:
Если вы добавите следующий комментарий в начало файла ruby, тогда каждый строковый литерал во всем файле будет неизменным. Это очень полезно, когда вы пытаетесь оптимизировать свое приложение для многопоточной среды.
# frozen_string_literal: true
Или вы даже можете запустить процесс Ruby с переключателем --enable-frozen-string-literal
.
Одно из объяснений того, почему вы видите такое постоянное зависание констант в популярных проектах, заключается в том, что они используют Rubocop, анализатор кода. .
Это стандартное правило Rubocop, которое не должно быть изменяемым по причинам, упомянутым выше @spickermann.
Похожие вопросы
Связанные вопросы
Новые вопросы
ruby-on-rails
Ruby on Rails - это полнофункциональная платформа веб-приложений с открытым исходным кодом, написанная на Ruby. Он следует популярной модели фреймворка MVC и известен своим подходом «соглашение поверх конфигурации» при разработке приложений.