如何从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,(  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中问这个问题,因为很多人都不知道如何使用library(persistency)

关于库(持久性)的好处之一是,一旦配置正确,它就可以管理数据(事实和谓词)的保存和加载。

由于您给出了由library(persistency)创建的文件的示例,因此我认为它可以正常工作。

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

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

所以回答你的问题

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

只需访问事实,就好像它们在Prolog数据库中一样

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

在SWI-Prolog论坛上使用库(持久性)创建Wiki时,却排在我的长名单上,这是最新的完整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',add_user('Ellen',developer),add_user('Stan',add_user('Eric',administrator).

文件:load_facts.pl

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

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom,[]).

示范

  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)
        ).

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

  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.

享受!