将对象保存到Logtalk中的文件

时间:2018-12-19 09:25:09

标签: object serialization prolog save logtalk

我已经编写了一个prolog项目,现在我必须将其更改为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 :(得分:0)

根据对象的依赖性,对动态对象进行序列化通常会很复杂,但是您的情况似乎更简单,因为每个对象仅依赖于一个协议并且仅包含事实。

在使用支持保存状态的后端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.

但是,这只是一个起点。可以通过几种方式进行改进,但主要需要有关特定序列化方案的更多详细信息。

更新

根据上面的代码https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/serialization

向Logtalk git版本添加了serialization示例