SWI-prolog 中的动态规则断言

问题描述 投票:0回答:2

我正在尝试使用 SWI-prolog 将规则动态添加到知识库,其中规则的主体事先未知。

所需的规则看起来像这样:

rule(a) :- fact(1), fact(2).

通常您只需说明

assert((rule(a):-fact(1),fact(2))).

但问题是事实是在运行时决定的(断言之前事实的数量也是未知的)。

这就是为什么我想知道是否有可能断言一个规则,其中主体由一系列事实组成,例如

[fact(1), fact(2)]

prolog metaprogramming
2个回答
7
投票

我们将创建一条规则

newrule(X) :- w,x,y,z(X)

规则的主体是一个元组1,其形式为(w,x,y...)。

对于不同的身体长度,从没有身体开始:

assert(goal).  
assert(goal:-cond).  
assert(goal:-(cond1,cond2)).

元组运算符是逗号(`,'),如 ','(a,b) == (a,b).

%%%%
%%%% Name: runtime.pl -- Runtime rule insertion.
%%%%
create_a_rule :- 
    Cond=[w,x,y,z(X)],
    Head=newrule(X),
    list_to_tuple(Cond,Body),
    dynamic(Head),
    assert(Head :- Body),
    listing(Head).

/*
This is a [l,i,s,t], and this is a (t,u,p,l,e).  
Convertng list to tuple:  
[]    -> undefined  
[x]   -> (x) == x  
[x,y] -> (x,y).  
[x,y,z..whatever] = (x,y,z..whatever)  
*/

list_to_tuple([],_) :- 
    ValidDomain='[x|xs]',
    Culprit='[]',
    Formal=domain_error(ValidDomain, Culprit),
    Context=context('list_to_tuple','Cannot create empty tuple!'),
    throw(error(Formal,Context)).

list_to_tuple([X],X).

list_to_tuple([H|T],(H,Rest_Tuple)) :-
    list_to_tuple(T,Rest_Tuple).

:- create_a_rule.
:- listing(newrule).

--

有两个列表。 第一个列表是在

listing()
中调用
create_a_rule()
的结果。 第二个清单来自最后一个源代码行的
listing()
命令。

?- [runtime].
:- dynamic newrule/1.

newrule(A) :-
    w,
    x,
    y,
    z(A).

:- dynamic newrule/1.

newrule(A) :-
    w,
    x,
    y,
    z(A).

% runtime compiled 0.01 sec, 1,448 bytes
true.

[1]:这实际上是一个 Prolog 逗号列表


2
投票

建议更改 frayser 的列表:

list_to_tuple([X],X).

list_to_tuple([A,B],(A,B)).

list_to_tuple([A,B|T],(A,B,Rest_Tuple)) :-
    list_to_tuple(T,Rest_Tuple).

如果第一个变量是空列表,这些子句就不需要出现异常:它只会失败。这也意味着回溯时你永远不会遇到断言。

但是,您可能仍然希望设置异常子句,因此您仍然可以将其放入以捕获尝试与 [] 进行统一的情况。 (不过,回溯时它不会击中它。)

© www.soinside.com 2019 - 2024. All rights reserved.