首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将对象保存到Logtalk中的文件

将对象保存到Logtalk中的文件
EN

Stack Overflow用户
提问于 2018-12-19 17:25:09
回答 1查看 55关注 0票数 1

我已经写了一个prolog项目,现在我必须将它更改为Logtalk文件。在代码中,我可以用下面的代码向另一个prolog文件断言新的事实:

代码语言:javascript
复制
:- 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中做一些类似的事情,但不是使用事实,而是对象。我知道如何创建新对象(通过带协议的create_object/4 ),但我不知道如何将其保存在文件中作为数据库。

协议看起来像这样:

代码语言:javascript
复制
:- protocol(student).

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

:- end_protocol.

有人能帮我保存这些对象吗?

EN

回答 1

Stack Overflow用户

发布于 2018-12-19 18:29:55

一般来说,序列化动态对象可能很复杂,这取决于对象的依赖关系,但您的情况似乎比较简单,因为每个对象只依赖于一个协议,并且只包含事实。

当使用支持保存状态的后端Prolog系统(例如,SICStus Prolog、SWI-Prolog或YAP)时,一个简单的解决方案是创建一个保存状态。由于保存的状态没有标准,因此此解决方案必然是不可移植的。

当无法保存状态或寻求可移植的解决方案时,我们需要为保存的数据定义一种格式,以便我们可以在加载和恢复对象时解释它。让我们假设我们希望将对象恢复为动态对象(就像它们最初是使用create_object/4谓词创建的一样),并使用一个简单的表示data/1来表示保存的状态。我们可以定义一个通用的serializer对象,如下所示(未测试):

代码语言:javascript
复制
:- 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.

然而,这只是一个起点。它可以通过几种方式进行改进,但这主要需要关于特定序列化场景的更多细节。

更新

基于上面的代码,在Logtalk git版本中添加了一个serialization示例:https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/serialization

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53848111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档