Сохранить объект в файл в Logtalk - PullRequest
0 голосов
/ 19 декабря 2018

Я написал проект пролога, и теперь мне нужно изменить его на файл Logtalk.В коде я могу утверждать новые факты в другом файле пролога с кодом:

:- dynamic(student/5).
:- use_module(library(persistency)).

:- persistent(student(id, name, surname, mark, studies)).
:- initialization(db_attach('student_database.pl', [])).

add_student(ID, Name, Surname, Mark, Studies):-
    with_mutex(student_db, assert_student(ID, Name, Surname, Mark, Studies)).

Теперь я хочу сделать нечто подобное в Logtalk, но не с фактами, а с объектами.Ofc Я знаю, как создать новый объект (по протоколу create_object/4), но не знаю, как сохранить его в файл в качестве базы данных.

Протокол выглядит так:

:- protocol(student).

    :- public([
        id/1,
        name/1,
        surname/1,
        studies/1,
        marks/1
    ]).

:- end_protocol.

Может кто-нибудь помочь мне с сохранением этих объектов?

1 Ответ

0 голосов
/ 19 декабря 2018

Сериализация динамических объектов в целом может быть сложной, в зависимости от зависимостей объектов, но ваш случай кажется проще, поскольку каждый объект зависит только от одного протокола и содержит только факты.

При использовании серверной системы 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...