Prolog中的谓词控制
对Prolog谓词控件有好奇心 假设我有一个谓词f(a,X)和g(B)Prolog中的谓词控制,prolog,predicate,Prolog,Predicate,对Prolog谓词控件有好奇心 假设我有一个谓词f(a,X)和g(B) 如果c返回false,我如何在谓词f(A,X)中继续计算g(X)。考虑例如 ?- false, writeln('Hello World!'). false. ?- ignore(false), writeln('Hello World!'). Hello World! true. 但是,如果c失败,为什么要继续?用例是什么 我在SWI Prolog中测试了这段代码,我不确定其他Prolog是否有false/0和igno
如果c返回false,我如何在谓词
f(A,X)
中继续计算g(X)
。考虑例如
?- false, writeln('Hello World!').
false.
?- ignore(false), writeln('Hello World!').
Hello World!
true.
但是,如果c
失败,为什么要继续?用例是什么
我在SWI Prolog中测试了这段代码,我不确定其他Prolog是否有false/0
和ignore/1
。
后者可以这样定义:
ignore(Goal) :- Goal, !.
ignore(_).
如果您的意图是定义
f(A,X)
,以便评估g(X)
是否c
失败,则:
->
)和/或析取(;
)、或对其进行编码f(A,X)
不需要用c
来定义。这假设c
没有任何副作用(例如,使用assert
断言数据库事实,或将IO打印到流),这些副作用会改变环境,并且在c
失败时无法撤消,在这种情况下,首选第一个选项李>
使用析取有几种选择,例如:
f(A,X) :- ((a, b, c) ; (a, b)), g(X).
此定义(如上)根本不依赖于c
,但它将始终执行c
(只要a
和b
成功)。析取(;
)允许PROLOG在c
完全失败的情况下回溯尝试再次执行a、b
,并继续执行g(X)
。请注意,这相当于:
f(A,X) :- a, b, c, g(X).
f(A,X) :- a, b, g(X).
为了使PROLOG不会因为第二个(相同的)头谓词f(A,X)
而回溯计算f(A,X)
两次,您可以选择在第一个子句中的c
子目标之后立即放置一个cut(!
),如果您的实现支持的话。切割放在c
之后,因为如果c
失败,我们不希望解释器承诺选择f(A,X)
子句,相反,我们希望解释器退出该子句并尝试下一个子句,有效地忽略c
并继续处理g(X)
还要注意,此解决方案依赖于a
和b
没有副作用,因为当c
失败时,a
和b
会再次执行。如果所有a
、b
和c
都有副作用,您可以尝试使用暗示:
无论
c
是否失败,这也将始终有效地执行g(X)
,并且如果c
失败,将不会再次执行a
和b
。这种单一条款的定义也不会像前面的建议那样留下选择点 +1询问为什么这会有用。可移植的失败谓词是fail
,顺便说一句。(实现起来很简单:fail:-0=1.
)如果c
失败,您可能希望继续的一种情况是c
有副作用;有关更多详细信息,请参见我对这个问题的回答。
f(A,X) :- a, b, c, g(X).
f(A,X) :- a, b, g(X).
f(A,X) :- a, b, (c -> g(X) ; g(X)).