Сериализация динамических объектов в целом может быть сложной, в зависимости от зависимостей объектов, но ваш случай кажется проще, поскольку каждый объект зависит только от одного протокола и содержит только факты.
При использовании серверной системы Prolog, которая поддерживает сохраненные состояния (например, SICStus Prolog, SWI-Prolog или YAP), простое решение заключается в создании сохраненного состояния.Поскольку не существует стандарта для сохраненных состояний, это решение обязательно непереносимо.
Когда сохраненные состояния невозможны или требуется портативное решение, нам необходимо определить формат для сохраненных данных, чтобы мы моглиинтерпретировать его при загрузке и восстановить объекты.Давайте предположим, что мы хотим восстановить объекты как динамические объекты (как они были изначально созданы с использованием предиката create_object/4
) и использовать простое представление data/1
для сохраненного состояния.Мы можем определить общий serializer
объект следующим образом (не проверено):
:- object(serializer).
:- public([
save/2,
restore/1
]).
save(Protocol, File) :-
protocol_property(Protocol, public(Predicates)),
open(File, write, Stream),
write_canonical(Stream, protocol(Protocol)), write(Stream, '.\n'),
forall(
conforms_to_protocol(Object, Protocol),
save_object(Object, Predicates, Stream)
),
close(Stream).
save_object(Object, Predicates, Stream) :-
object_data(Predicates, Object, [], Data),
write_canonical(Stream, data(Data)), write(Stream, '.\n').
object_data([], _, Data, Data).
object_data([Functor/Arity| Predicates], Object, Data0, Data) :-
functor(Fact, Functor, Arity),
findall(Fact, Object::Fact, Data1, Data0),
object_data(Predicates, Object, Data1, Data).
restore(File) :-
open(File, read, Stream),
read_term(Stream, Term, []),
restore_object(Term, _, Stream),
close(Stream).
restore_object(end_of_file, _, _).
restore_object(protocol(Protocol), Protocol, Stream) :-
read_term(Stream, Term, []),
restore_object(Term, Protocol, Stream).
restore_object(data(Data), Protocol, Stream) :-
create_object(_, [implements(Protocol)], [], Data),
read_term(Stream, Term, []),
restore_object(Term, Protocol, Stream).
:- end_object.
Однако это только отправная точка.Он может быть улучшен несколькими способами, но для этого требуется больше подробностей о конкретном сценарии сериализации.
Обновление
Добавлен пример serialization
в версию Logtalk git на основепо коду выше: https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/serialization