Prolog 中 `if_/3` 运算符的目标扩展

Goal expansion for an `if_/3` operator in Prolog

我正在编写一个标记器,我想在我的代码中使用 if_/3 to preserve

左边的代码看起来像下面的代码1——但我希望它看起来像右边的代码。

if_(Cond1_1,                       %     (   Cond1_1
    Then1,                         %     *=> Then1
    if_(Cond2_1,                   %     ;   Cond2_1
        Then2,                     %     *=> Then2
        if_(Cond3_1,               %     ;   Cond3_1
            Then3,                 %     *=> Then3
            if_(Cond4_1,           %     ;   Cond4_1
                Then4,             %     *=> Then4
                if_(Cond5_1,       %     ;   Cond5_1
                    Then5,         %     *=> Then5
                    Else5          %     ;   Else5
   )   )   )   )   ).              %     ).

为了在 SWI-Prolog 中将 (*=>)/2 重写为 if_/3,我想到了:

:- op(1050,xfy,*=>).

:- multifile goal_expansion/2.
goal_expansion((Cond *=> Then ; Else), if_(Cond,Then,Else)).
goal_expansion( Cond *=> Then        , (call(Cond,true), call(Then))).

"完成,"我以为...

但是看了SWI-Prolog documentation for goal_expansion/2之后我开始怀疑了:

Only goals appearing in the body of clauses when reading a source file are expanded using this mechanism, and only if they appear literally in the clause, or as an argument to a defined meta-predicate that is annotated using `0' (see meta_predicate/1). Other cases need a real predicate definition.

所以这是我的实际问题:我是否也需要一个真正的谓词定义?


脚注 1:实际代码有更长的 else if 链。

你需要一个 if_/3 谓词定义,至少要赋值 它是一个元谓词声明,否则扩展将停止, 如果 if_/3 本身没有元谓词声明。

你可以自己试试,我只用这个扩展:

:- op(1050,xfy,*=>).
:- multifile goal_expansion/2.
goal_expansion((Cond *=> Then ; Else), if_(Cond,Then,Else)).

没有元谓词声明:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)

?- expand_goal((a *=> b; c *=> d; e), X).
X = if_(a, b,  (c*=>d;e)).

使用元谓词声明:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)

:- meta_predicate if_(1,0,0).
?- expand_goal((a *=> b; c *=> d; e), X).
X = if_(a, b, if_(c, d, e)).

这与 SWI-Prolog 和 Jekejeke Prolog 中的行为相同。您可以研究源代码以更好地理解为什么需要元谓词声明。

示例见此处:
https://github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/jekpro/frequent/standard/expand.p#L220