Почему `ObjectSpace.each_object(String)` содержит практически любую строку?

После комментариев Майка ХР и Стефана к моему вопросу я заметил, что ObjectSpace.each_object(String) включает в себя практически любую строку, о которой я могу думать:

strings = ObjectSpace.each_object(String)
strings.include?("some random string") # => true

или же

strings = ObjectSpace.each_object(String).to_a
strings.include?("some random string") # => true

я думал так strings должен включать только строки, которые существовали на тот момент. Почему он включает в себя практически любую строку?

Тем не менее, когда я считаю длину strings, он возвращает конечное число:

ObjectSpace.each_object(String).to_a.length # => 15780

Это наблюдается в интерпретаторе Ruby 2.1.2p95 (редакция 2014-05-08 45877) [x86_64-linux] и irb.

Имеет ли это какое-либо отношение к оптимизации строкового литерала, представленной в Ruby 2.1?

2 ответа

Решение

При написании кода в IRB строки добавляются в ObjectSpace как они набраны:

strings = ObjectSpace.each_object(String)
strings.include?("some random string") # => true

strings = ObjectSpace.each_object(String).to_a
strings.include?("some other random string") # => false

При попытке сделать это внутри rb файл, текст уже там, потому что он добавляется, когда файл анализируется.

test.rb

strings = ObjectSpace.each_object(String)
strings.include?("some random string") # => true

strings = ObjectSpace.each_object(String).to_a
strings.include?("some other random string") # => true

strings = ObjectSpace.each_object(String).to_a
strings.include?("some other random string " + "dynamically built") # => false

Это потому, что для передачи "какой-то случайной строки" include? метод на ObjectSpace"s each_object итератор, вы должны сначала создать строку "некоторую случайную строку".

Просто спрашивая ObjectSpace о существовании "некоторой случайной строки", вы создаете "некоторую случайную строку", поэтому, конечно, она существует в объектном пространстве. Видишь, что я говорю? Так что это объясняет ваш первый пример.

Во втором примере, когда вы получаете массив строковых объектов, прежде чем ссылаться на "некоторую случайную строку", вы думаете, что получите false. Как вы заметили, это не так. Я предполагаю, что это потому, что вы используете строковый литерал, а Ruby оптимизирует ваш код, создавая строку перед тем, как вы на самом деле ссылаетесь на нее. Я не знаю достаточно о внутренностях Руби, чтобы вдаваться в подробности.

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