如何在Prolog中将谓词作为参数传递给另一个谓词?

How*_*heF 5 parameters expression predicate prolog

我有以下3个谓词:

times(X, Y):-
    Result is X * Y.
minus(X, Y):-
    Result is X - Y.
plus(X, Y):-
    Result is X + Y.
Run Code Online (Sandbox Code Playgroud)

我想通过例如times(2,2)plus(X, Y)这样的plus(times(2,2), minus(X, Y))

Dan*_*ons 5

我不清楚你的问题标题和问题文本之间的关系,我认为@false可能是对的,这里对Prolog存在更根本的误解。我不知道这是否真的满足您的需求,但这里的替代方案是编写您自己的评估器。

eval(times(X,Y), Result) :-
    eval(X, XResult),
    eval(Y, YResult),
    Result is XResult * YResult.
eval(minus(X,Y), Result) :-
    eval(X, XResult),
    eval(Y, YResult),
    Result is XResult - YResult.
eval(plus(X,Y), Result) :-
    eval(X, XResult),
    eval(Y, YResult),
    Result is XResult + YResult.
Run Code Online (Sandbox Code Playgroud)

eval/2需要对每个规则的主体内部进行递归调用来处理类似的情况plus(times(2,2), minus(X, Y))。那么你需要一个数字规则:

eval(Num, Num) :- number(Num).
Run Code Online (Sandbox Code Playgroud)

这对于这样的情况非常有用:

?- eval(plus(times(2,2), minus(7,1)), Result).
Result = 10.
Run Code Online (Sandbox Code Playgroud)

对于这样的情况,它对你没有任何好处:

?- eval(plus(times(2,2), minus(X,Y)), Result).
ERROR: Out of local stack
Run Code Online (Sandbox Code Playgroud)

当然,如果我们在到达那里之前建立了 X 和 Y 的绑定,那么它会起作用,但如果您希望它为 X 和 Y 生成可能的解决方案,那么您就不走运了,您需要使用clpfd. 如果你追踪的话,这个奇怪错误的原因是因为number(X)when Xis unbound 是假的,所以它实际上生成了涉及时间、减号和加号结构的新子句并尝试它们,这不是你想要的求值器。

编辑:实施printterm/1.

eval/2谓词向您展示如何执行递归树遍历。原理与制作漂亮的打印机相同。我很懒所以只画了草图,细节你得自己填写。

printterm(T) :- format_term(T, Formatted), write(Formatted), nl.

format_term(plus(X,Y), Formatted) :- 
  format_term(X, XFormatted),
  format_term(Y, YFormatted),
  format(atom(Formatted), '(~a + ~a)', [XFormatted, YFormatted]).

% other format_term clauses here for other arithmetic expressions

format_term(X, X) :- number(X).
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!