Как мне десериализовать в Psych для возврата существующего объекта, такого как объект класса?
Чтобы выполнить сериализацию класса, я могу сделать
require "psych"
class Class
yaml_tag 'class'
def encode_with coder
coder.represent_scalar 'class', name
end
end
yaml_string = Psych.dump(String) # => "--- !<class> String\n...\n"
, но если я попытаюсьвыполняя Psych.load
, я получаю анонимный класс, а не класс String.
Обычный метод десериализации - Object#init_with(coder)
, но он только изменяет состояние существующего анонимного класса, тогда как яжелая, чтобы класс String.
Psych::Visitors::ToRuby#visit_Psych_Nodes_Scalar(o)
имел случаи, когда вместо того, чтобы модифицировать существующие объекты с помощью init_with
, они удостоверяются, что в первую очередь создается нужный объект (например, вызывая Complex(o.value)
для десериализациикомплексное число), но я не думаю, что мне следовало бы использовать этот метод.
Обречен ли я работать с излучением низкого или среднего уровня, или я что-то упустил?
Справочная информация
Я опишу проект, зачем ему нужны классы, и почему ему нужна (де) сериализация.
Проект
Цели Small Eigen Colliderсоздать случайный вкусks для запуска Ruby.Первоначальная цель состояла в том, чтобы увидеть, возвращали ли разные реализации Ruby (например, Rubinius и JRuby) одинаковые результаты при выполнении одних и тех же случайных задач, но я обнаружил, что это также хорошо для обнаружения способов обойти ошибки Rubinius и YARV.
Каждая задача состоит из следующих элементов:
receiver.send(method_name, *parameters, &block)
, где receiver
- случайно выбранный объект, method_name
- имя случайно выбранного метода, а *parameters
-массив случайно выбранных объектов.&block
не очень случайный - в основном это эквивалентно {|o| o.inspect}
.
Например, если получатель был "a", имя метода было бы: casecmp, а параметры было ["b"], тогда вы бывызывать
"a".send(:casecmp, "b") {|x| x.inspect}
, что эквивалентно (так как блок не имеет значения)
"a".casecmp("b")
Small Eigen Collider запускает этот код и регистрирует эти входы, а также возвращаемое значение.В этом примере большинство реализаций Ruby возвращают -1, но на одном этапе Rubinius возвращает +1.(Я подал это как ошибку https://github.com/evanphx/rubinius/issues/518, и сопровождающие Rubinius исправили ошибку)
Зачем нужны классы
Я хочу иметь возможность использовать объекты классов в своем Small EigenКоллайдер.Обычно они являются получателями, но они также могут быть одним из параметров.
Например, я обнаружил, что один из способов segfault YARV - это сделать
Thread.kill(nil)
В этом случае, receive - объект класса Thread, а параметры - [nil].(Отчет об ошибке: http://redmine.ruby -lang.org / Issues / Show / 4367 )
Почему требуется (де) сериализация
Малый собственный коллайдер нуждается в сериализации дляпара причин.
Во-первых, использование генератора случайных чисел для генерации серии случайных задач каждый раз нецелесообразно.JRuby имеет другой встроенный генератор случайных чисел, так что даже при наличии одного и того же начального числа PRNG он будет выполнять разные задачи для YARV.Вместо этого я создаю список случайных задач один раз (первый запуск ruby bin / small_eigen_collider), инициализирую сериализацию списка задач в tasks.yml, а затем выполняю последующие запуска программы (используя разныеРеализации Ruby) читайте в этом файле tasks.yml, чтобы получить список задач.
Еще одна причина, по которой мне нужна сериализация, заключается в том, что я хочу иметь возможность редактировать список задач.Если у меня длинный список задач, приводящий к ошибке сегментации, я хочу сократить список до минимума, необходимого для возникновения ошибки сегментации.Например, следующая ошибка https://github.com/evanphx/rubinius/issues/643,
ObjectSpace.undefine_finalizer(:symbol)
сама по себе не вызывает ошибку сегментации, и при этом
Symbol.all_symbols.inspect
, но если вы поставитедва вместе, это сделал.Но я начал с тысяч задач, и мне нужно было свести их обратно к этим двум задачам.
Имеет ли смысл десериализация, возвращающая существующие объекты класса, в этом контексте, или вы думаете, что есть лучший способ?