如何在写入 .pl 文件的 pyswip 中进行断言

How to make assertion in pyswip written to .pl file

我有一个包含事实和规则的预填充“.pl”文件。我使用 pyswip 的 consult() 方法打开文件。例如,关于对象的可拾取性有两个事实:

pickable_object(pen).
pickable_object(paper).

现在,在我使用 pyswip 添加新事实后:

prolog.assertz('pickable_object(light)')

查询

for result in prolog.query('pickable_object(X)'):
    print(result)

完美运行并打印:

{'X': 'pen'} {'X': 'paper'} {'X': 'light'}

但是,断言不会写入“.pl”文件。我该如何启用它?

作为一种解决方法,我只是将新的子句字符串附加为一个新行,将其视为一个文本文件。

如果您只对在 Prolog 运行 之间保存和恢复动态谓词的状态感兴趣,最简单的方法可能是使用 persistency library。对于您的示例,您可以拥有以下文件 myfacts_db.pl:

:- module(myfacts_db,
          [ attach_myfacts_db/1,       % +File
            get_myfact/1,              % ?Fact
            set_myfact/1               % +Fact
          ]).
:- use_module(library(persistency)).

:- persistent
        myfact(fact:any).

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

get_myfact(pickable_object(pen)).
get_myfact(pickable_object(paper)).

get_myfact(Fact) :-
        myfact(Fact).

set_myfact(Fact) :-
        assert_myfact(Fact).

如果我们 运行 Prolog 第一次使用新模块,我们得到:

$ swipl

?- use_module(myfacts_db).
true.

?- attach_myfacts_db('test.pl').
true.

?- findall(X,get_myfact(pickable_object(X)),Objects).
Objects = [pen, paper].

?- set_myfact(pickable_object(light)).
true.

?- findall(X,get_myfact(pickable_object(X)),Objects).
Objects = [pen, paper, light].

?- halt.

如果数据库文件 test.pl 不存在,将创建它。如果我们再次启动 Prolog,我们有:

$ swipl

?- use_module(myfacts_db).
true.

?- attach_myfacts_db('test.pl').
true.

?- findall(X,get_myfact(pickable_object(X)),Objects).
Objects = [pen, paper, light].

请注意,这样创建的数据库并不是简单的事实列表,而是看起来像这样(额外的东西用于处理同步):

$ cat test.pl
created(1565656419.9478514).
assert(myfact(pickable_object(light))).

如果你真的想要一个只列出 "pure" 事实 pickable_object(light)). 等的文件,我不知道 SWI-Prolog 的任何内置方法会支持这一点,所以在那种情况下,您确实必须通过文件 I/O 写入和读取文件(或相应地修改数据库文件)。然而,一旦您还想支持删除事实、共享访问等,这将变得棘手。