2

N > Order である限り、データベースを実行する必要があるこのコードを取得しました。私のコードは一度だけ実行されます:/ ?

display(N) :-
    w(Order,_,Word,Class),
    N > Order -> (write(Word), write(' '), write(Class)),
    nl, fail .

前もって感謝します!

4

2 に答える 2

4

あなたの問題はあなたが使う方法です->

まず、コードは次のように解釈されます。

display(N) :-
    (  w(Order,_,Word,Class),
       N > Order ) 
    ) -> 
      (  write(Word), 
         write(' '), 
         write(Class)
      ),
    nl, fail .

->選択ポイントを破棄します。これは、再度呼び出そうとしないことを意味しますw/3

あなたは(おそらく)それをこのように機能させることができます:

display(N) :-
    (w(Order,_,Word,Class),
    N > Order )-> (write(Word), write(' '), write(Class)),
    nl, fail .

しかし、結局のところ、それは本当に醜いコードであり、あなたが見てきたように、バグが発生しやすいです。より良い方法は、以下を使用することforall/2です。

display2(N) :-
    forall(w(Order, _, Word, Class),
           (N > Order ->
           writef("%t %t \n", [Word,Class]); true)).

それでも、これはデータベース全体を調べ、もしあれば印刷しますN>Order。これが望ましい動作であるかどうかは説明から少し不明確ですが、より大きな最初の要素で停止したい場合は、次のようにすることができます。

display2(N) :-
    catch((forall(w(Order, _, Word, Class),
           (N > Order ->
           writef("%t %t \n", [Word,Class]); throw(end))), end, true)).

それを行うための最も宣言的な方法ではありませんが、それが何であるかを知らずにモデル化するための最良の方法はわかりませんw/4(これはいくつかのプロローグ句であると想定しましたが、ODBCレイヤーを介してDBにアクセスする述語である可能性があります)

于 2012-10-12T10:58:55.187 に答える
3

「else」ブランチを忘れたと思います。(->)/2 の優先順位は (,)/2 よりも高く、意図した順序を阻害します。試す

display(N) :-
    w(Order,_,Word,Class),
    ( N > Order -> write(Word), write(' '), write(Class), nl ; true ),
    fail .
于 2012-10-12T10:53:40.010 に答える