Сбор объектов, которые не обязательно назначены никаким переменным / константам

Объекты, которые не присвоены какой-либо переменной / константе, немедленно исчезают (при нормальных обстоятельствах). В следующем, строка "foo" не захвачен ObjectSpace.each_object(String) в третьей строке:

strings = ObjectSpace.each_object(String).to_a
  "foo"
ObjectSpace.each_object(String).to_a - strings # => []

Можно ли захватывать объекты, которые не обязательно назначены каким-либо переменным / константам или частью каких-либо переменных / констант? Я особенно заинтересован в захвате строк. Соответствующий домен может быть файлом или блоком. Я ожидаю что-то вроде следующего:

capture_all_strings do
  ...
  "a"
  s = "b"
  @s = "c"
  @@s = "d"
  S = "e"
  %q{f}
  ...
end
# => ["a", "b", "c", "d", "e", "f"]

1 ответ

Решение

Ruby создает строковые экземпляры при разборе вашего файла. Вот пример: строка

"aaa #{123} zzz"

анализируется как:

$ ruby --dump=parsetree -e '"aaa #{123} zzz"'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_DSTR (line: 1)
#     +- nd_lit: "aaa "
#     +- nd_next->nd_head:
#     |   @ NODE_EVSTR (line: 1)
#     |   +- nd_body:
#     |       @ NODE_LIT (line: 1)
#     |       +- nd_lit: 123
#     +- nd_next->nd_next:
#         @ NODE_ARRAY (line: 1)
#         +- nd_alen: 1
#         +- nd_head:
#         |   @ NODE_STR (line: 1)
#         |   +- nd_lit: " zzz"
#         +- nd_next:
#             (null node)

На этапе синтаксического анализа есть два строковых литерала, "aaa " а также " zzz":

#     +- nd_lit: "aaa "
#     ...
#         |   +- nd_lit: " zzz"

инспектирование ObjectSpace подтверждает, что эти строки были созданы:

$ ruby -e '"aaa #{123} zzz"; ObjectSpace.each_object(String) { |s| p s }' | egrep "aaa|zzz"
"\"aaa \#{123} zzz\"; ObjectSpace.each_object(String) { |s| p s }\n"
"aaa 123 zzz"
" zzz"
"aaa "

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

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