我有一組規則和相同的斷言事實的集合撤消只有一個規則,而不是相同的謂詞的事實在序言
p(1).
p(2).
g(1,1).
h(3,2).
p(X):- g(X,Y).
p(X):- h(X,Y).
我願做一個retractall般的斷言和刪除只有規則而不是事實。所以像這樣的東西:
retractRules(p(X)).
在Prolog中如何做到這一點?
我有一組規則和相同的斷言事實的集合撤消只有一個規則,而不是相同的謂詞的事實在序言
p(1).
p(2).
g(1,1).
h(3,2).
p(X):- g(X,Y).
p(X):- h(X,Y).
我願做一個retractall般的斷言和刪除只有規則而不是事實。所以像這樣的東西:
retractRules(p(X)).
在Prolog中如何做到這一點?
您不能使用標準retract/1
謂詞來收回事實。諸如retract((p(_) :- Body))
之類的呼叫收回事實並將Body
例示爲true
。
假設你正在使用SWI-Prolog的,一個非便攜解決方案是使用clause/3
去規則的引用,然後刪除該條款用erase/1
這些引用。假設p/1
是一個動態的謂詞:
?- forall((clause(p(_), Body, Ref), Ref \== true), erase(Ref)).
你當然可以收回所有條款,然後斷言回的只有事實,但聽起來矯枉過正:
?- forall((retract(p(X) :- Body), Body == true), assertz(p(X)).
在GNU Prolog和SWI Prolog中使用的解決方案是使用'clause/2':'retractRules(R): - clause(R,B),B \ == true,retract(:-(R,B)), fail.' – lurker
我刪除了我以前的答案因我的邏輯缺陷只依靠retract/1
。
大廈使用clause/3
的保羅·莫拉的想法,這裏是一個使用ISO謂詞clause/2
的解決方案,使其成爲一個小更便攜:
retractRules(R) :-
clause(R, B),
B \== true,
retract(:-(R, B)),
fail.
retractRules(_).
這裏的假設是,你的規則是擺在首位動態創建,並使用適當的指令(:- dynamic
)聲明爲動態謂詞。例如,在什麼地方,你就會有這樣的事情:
assertz(:-(p(X), g(X,Y))).
你會得到一個「不連續的謂詞」因爲對'p條款的定義與此代碼警告/ 1'被的定義分離不同的謂詞。這就意味着「p(X)」條款根本不能被識別。 – lurker