Почему `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 оптимизирует ваш код, создавая строку перед тем, как вы на самом деле ссылаетесь на нее. Я не знаю достаточно о внутренностях Руби, чтобы вдаваться в подробности.