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, так далее.

Другие вопросы по тегам