0

別の述語へのすべての呼び出しが失敗した場合、どうすれば述語を呼び出すことができますか?

私は持っています:

foo(A, B, C, D) :-
    (bar1(Y,Z); bar2(L, K, M)),
    foo(A, B, C, D).

私が欲しいもの:

  • いつでも、成功した場合bar1/2bar2/3実行されることはありません。
  • すべてのbar1/2呼び出しが失敗した場合、bar2/3最終的に実行されます。

逆引きツリーのサンプル

            root                                           root                 
                                                            |
           /   \                                            |
          /     \          all bar1 failed                  |
         /       \                                          |
        / | \     \        ===>>>======>>>>                 |
       /  |  \     \                                        |
      F   F  F     F                                        E
time  0   1  2     3                                        4 

Abbreviation:
       Bar1 failed : F
       Bar2 executed : E
4

1 に答える 1

1

あなたは「ソフトカット」として知られているものを探しています、

A *-> B ; C.

これは次と同等です(A,B) ; (\+A,C)A少なくとも1回成功した場合、上記はと同等A,Bです。そうでない場合は、。と同等ですC。目標Aは再試行されません。

単純なif構成により、テスト述語は1回だけ成功します。

A -> B ; C.

目標が再試行されないことを除いて、と同等です(詳細についてはマニュアルを参照してください)(once(A),B) ; (\+A,C)A

したがって、あなたのケースは

foo(A, B, C, D) :-
    (bar1(Y,Z) *-> true ; bar2(L, K, M)),
    foo(A, B, C, D).

追加:一部のProlog実装では、この構成を使用できない場合が*->あります(gprologなど)。その場合、2つの可能性があります。また

(A , B) ; (\+A , C)

再試行しますがA、または(Aの書き込みgoal(X)

bagof(g(X), goal(X), L) -> ( member(g(X), L), B ) ; C 

もちろん、これにより副作用の順番が変わります。変数の名前Lは、で自由に表示されないように選択する必要がありますB

于 2012-06-04T18:22:26.073 に答える