Ruby 2.1 Замороженная нить
В Ruby 2.1 будет замороженная строка, чтобы объект не создавался заново каждый раз, когда интерпретатор пересекает его, т.е.
my_hash["abcd"f] = 123
Почему интерпретатор не может автоматически определить, что эта строка не изменится, и просто автоматически заморозить ее?
Или pre-ruby 2.1. Как любой код может изменить такую строку после запуска интерпретатора? Если мы говорим, что "abcd" нужно заморозить, то должен быть какой-то способ его изменить.
- ОБНОВЛЕНИЕ: вопрос выше был обновлен, поэтому приведенные ниже комментарии немного неуклюжи, но касались предыдущего примера кода, который был не так хорош.
- ОБНОВЛЕНИЕ: http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/ Ключи Ruby автоматически замораживаются.
2 ответа
Ruby - динамический язык. Статической компиляции не существует, и интерпретатору очень сложно заранее знать, кто в конечном итоге получит доступ к переменной и изменит ее.
Давайте посмотрим на следующий пример. У тебя есть string
str = "foo"
а потом в вашем коде у вас есть
str.upcase!
# => "FOO"
Этот пример довольно тривиален даже для простого парсера, который понимает, что строка видоизменена. Но давайте добавим еще немного сложности
str = "foo"
method = ["up", "case"]
str.send((method << "!").join)
# => "FOO"
Это дает точно такой же результат, как и раньше, но метод не статически закодирован в сценарии. Вместо этого это результат вычисления, которое затем динамически выполняется на строке во время выполнения.
Но подождите, давайте сделаем это еще сложнее.
str = "foo"
method = [ARGV.first, "case"]
str.send((method << "!").join) if ARGC.to_i > 0
# => "FOO"
В этом случае, если я передам аргумент из командной строки, метод преобразования будет вычислен, а затем применен к строке.
Как вы можете догадаться, единственный способ в обоих случаях знать, что str
будет изменено путем фактического выполнения кода.
Эти примеры также должны ответить на вашу вторую часть вопроса
Как любой код может изменить такую строку после запуска интерпретатора? Если мы говорим, что "abcd" нужно заморозить, то должен быть какой-то способ его изменить.
В качестве дополнительного примечания я хотел бы отметить, что функция "замороженных строковых литералов" недавно появилась, и теперь достаточно пометить переменную как frozen
,
В Ruby 2.1
"str".freeze
оптимизируется компилятором, чтобы возвращать одну общую замороженную строку при каждом вызове. Первоначально был реализован альтернативный синтаксис "str", но позже он был отменен.
По поводу вашего первого вопроса:
Потому что интерпретатор не может предвидеть, будет ли этот экземпляр строки впоследствии изменен каким-либо деструктивным методом.
По поводу вашего второго вопроса (после "Или"):
Любым из разрушительных методов на
String
, такие какreverse!
,prepend
,concat
, так далее.