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)).

尽管如此,这将检查整个数据库并打印 if 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 层访问数据库的谓词)

于 2012-10-12T10:58:55.187 回答
3

我认为您忘记了“其他”分支,并且 (->)/2 的优先级高于 (,)/2,从而抑制了预期的顺序。尝试

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