Prolog Design Pattern扩展模块谓词

Kor*_*nik 5 design-patterns module object prolog

想象一下,我们有familytree下面的模块(简单示例):

:- module(familytree, [         
        father/2,
        mother/2,
        %[...]    
    ]).    

father(X,Y) :- male(X),parent(X,Y).
father(unknown, _) :- male(unknown).

mother(X,Y) :- female(X),parent(X,Y).
mother(unknown, _) :- female(unknown).

sister(X,Y) :- female(X),parent(Z,X),parent(Z,Y), X \= Y.

%[... other relation predicates ... ]
Run Code Online (Sandbox Code Playgroud)

我想使用不同"dbs"的这个模块谓词,例如:

:- module(familytree_xyz, []).

male(james).
male(fred).
male(mike).

female(betty).
female(sandra).    

parent(james, fred).
parent(betty, fred).
Run Code Online (Sandbox Code Playgroud)

要么 :

:- module(familytree_simpson, []).

male(homer).
male(bart).

female(marge).
female(lisa).

parent(homer, bart).
%[...]
Run Code Online (Sandbox Code Playgroud)

我需要 :

  • 运行时选择db ,而不是在编译选择db .
  • 在同一时间使用一个或多个dbs.
  • 扩展数据库,例如.创建一个"familytree_simpson_extended"db模块,其他Simpson家族成员扩展"familytree_simpson"db模块(参见上面的例子)
  • SWI-Prolog的标准.

现在,我试着玩term_expansion/2,discontiguous/1,multifile/1,dynamic/1thread_local/1指令,但是:

  • term_expansion/2 似乎只能在编译时使用,
  • discontiguous/1,multifile/1不适应,
  • prolog中的动态dbs被视为" 邪恶 "练习,但是很多包和库都使用它(例如pengines,broadcast模块,httplib).
  • thread_local/1 没有很好的文档,似乎不常用于prolog源代码(swi-prolog).

通过使用动态谓词,我更新以前的代码如下:

%familytree.pl
:- module(familytree, [
        familytree_cleanup_db/0,
        familytree_use_db/1,
        %[... previous declarations ...]        
    ]).

dynamic male/1, female/1, parent/2.

familytree_cleanup_db :- 
    retractall(male/1), 
    retractall(female/1),
    retractall(parent/2).

familytree_use_db(ModuleName) :- 
    assert(male(X) :- ModuleName:male(X)),
    assert(female(X) :- ModuleName:female(X)),
    assert(parent(X,Y) :- ModuleName:parent(X,Y)).

%[... previous predicates ...]  
Run Code Online (Sandbox Code Playgroud)

而且:

%main.pl    
% use familytree tool predicates
:- use_module(familytree).

%load all familytree dbs at compile time.
:- use_module(familytree_xyz).
:- use_module(familytree_simpson).
:- use_module(familytree_simpson_extended).

main_xyz:- 
    familytree_cleanup_db,
    familytree_use_db(familytree_xyz),
    process.        

main_simpson_all :-
    familytree_cleanup_db,
    familytree_use_db(familytree_simpson),
    familytree_use_db(familytree_simpson_extended),
    process.

process :-
    findall(X, father(X,_), Xs),
    write(Xs).
Run Code Online (Sandbox Code Playgroud)

并且可以使用不同的db如下:

?- main_simpson_all.
[homer,homer,abraham]
true.
?- main_xyz.
[james]
true.
Run Code Online (Sandbox Code Playgroud)

所以,抱歉帖子的长度.问题:

  1. 使用此动态谓词解决方案时,有哪些标准,优点/缺点?这是一个好的解决方案吗?

  2. 在干净/健壮的代码中,prolog 的最佳实践/特定设计模式是什么?**

  3. 使用thread_local/1而不是dynamic/1 封装调用新线程以避免清理db是什么意思?