如何从 SWI-Prolog 中的库(持久性)获取数据?

How to get data from library(persistency) in SWI-Prolog?

我有这个模块:

:- module(data_db,
          [ attach_data_db/1,           % +File
            current_user_role/2,        % ?User, ?Role
            add_user/2,                 % +User, +Role
            set_user_role/2             % +User, +Role
          ]).
:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,administrator])).

attach_data_db(File) :-
        db_attach(File, []).

%%      current_user_role(+Name, -Role) is semidet.

current_user_role(Name, Role) :-
        with_mutex(data_db, user_role(Name, Role)).

add_user(Name, Role) :-
        assert_user_role(Name, Role).

set_user_role(Name, Role) :-
        user_role(Name, Role), !.
set_user_role(Name, Role) :-
        with_mutex(data_db,
                   (  retractall_user_role(Name, _),
                      assert_user_role(Name, Role))).

这是官方文档中的示例。所以我可以使用 db_attach 将数据添加到文件中,但我不明白如何从文件中获取数据。该文件包含:

created(1603178081.6254506).
assert(user_role('John',user)).
assert(user_role('John',user)).
assert(user_role(han,user)).

首先你真的应该问这个问题 SWI-Prolog forum as knowing how to use library(persistency) 很多人都不知道。

library(persistency) 的一个好处是,一旦您正确配置它,它就会管理数据(事实和谓词)的保存和加载。

既然你给出了一个由 library(persistency) 创建的文件的例子,我会认为你已经正确地工作了。

您的问题与我第一次使用 library(persistency) 时遇到的问题相同,因为我希望将事实存储在文件中,就像我手动输入它们一样。这不是您应该如何看待库(持久性),而是将其视为创建命令日志,并且在打开日志时回放这些命令。

由于它是命令日志,这就是为什么您看到 assert(user_role('John',user)). 而不是 user_role('John',user). 的原因。当文件被 library(persistency) 打开和播放时,该命令将事实断言到内存中的 Prolog 数据库中,这是由 library(persistency) 自动完成的。

所以回答你的问题

How to get data from library(persistency) in SWI-Prolog?

只需像在 Prolog 数据库中一样访问事实,例如

?- user_role('John',Role).
Role = user.

在使用我编写的工作代码创建 Wiki at the SWI-Prolog forum for using library(persistency) is on my long list, here is the latest complete post 时。

您需要单击三角形展开详细信息才能查看代码。


这是一个基于您的问题的完整工作示例。有两个 Prolog 源文件,一个用于将一些事实保存到日志中,然后停止 Prolog 顶层以证明数据不是通过 Prolog 数据库传递的,而是通过日志文件传递的。然后第二个 Prolog 源将访问日志文件,使顶层的事实可用。

文件:create_facts.pl

:- module(create_facts,[]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).

:- initialization(main).

add_user(Name, Role) :-
        (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).

main :-
    add_user('John',user),
    add_user('Mary',user),
    add_user('Ellen',developer),
    add_user('Stan',user),
    add_user('Eric',administrator).

文件:load_facts.pl

:- module(load_facts,[
                user_role/2
        ]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).

示范[​​=30=]

  1. 查阅 create_facts.pl 将自动 运行 main 在日志文件中创建事实。
?- ['create_facts'].
true.
  1. 暂停 Prolog 顶层以表明事实仅在日志文件中传递。此外,在执行 halt 之前,日志文件可能不完整,并且仍会被 SWI-Prolog 顶层持有。
?- halt.

步骤 1 中创建的日志文件

文件:user.joural

created(1603198849.086677).
assert(user_role('John',user)).
assert(user_role('Mary',user)).
assert(user_role('Ellen',developer)).
assert(user_role('Stan',user)).
assert(user_role('Eric',administrator)).

如果你愿意,你可以 运行 重复第 1 步和第 2 步,这样就不会重复日志中的事实,因为

        (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).

检查事实是否存在,如果不存在则将事实断言到日志中。

  1. 参考 load_facts.pl 将日志文件中的事实加载到 Prolog 数据库中。
?- ['load_facts'].
true.
  1. 就像正常创建一样访问事实
?- user_role(Name,Role).
Name = 'John',
Role = user ;
Name = 'Mary',
Role = user ;
Name = 'Ellen',
Role = developer ;
Name = 'Stan',
Role = user ;
Name = 'Eric',
Role = administrator.

尽情享受吧!