2

我有以下问题:

序言编:

man(thomas, 2010).
man(leon, 2011).
man(thomas, 2012).
man(Man) :- once(man(Man, _).

问题:

?- man(thomas).
true ;        %i want only on true even if there are more "thomas" *working because of once()*

?- man(X).
X = thomas ;  %i want all man to be listed *isn't working*

目标:

?- man(thomas).
true ;

?- man(X).
X = thomas ;
X = leon ;
X = thomas ;

我不明白为什么会发生这种情况,但仍然想得到所有人的名字。所以我的解决方案是查看“Man”是否被初始化,如果是,则比“once ..”否则......类似这样的东西:

man(Man) :- (->check<-,once(man(Man, _)); man(Man, _).

在“检查”上应该是检查变量“Man”是否被填充的代码。

这可能吗?

4

2 回答 2

4

实现此目的的一种方法如下:

man(X) :-
    (nonvar(X), man(X, _)), !
    ;
    man(X, _).

或者,更优选的是:

man(X) :-
    (   var(X)
    ->  man(X, _)
    ;   once(man(X, _))
    ).

切割将确保(至多)对实例化的解决方案只有一个解决方案X,而非实例化的情况将运行它的过程。请注意,通过剪切,您不需要once/1. 没有削减不能按预期工作的原因once/1是回溯仍然会回来并采用“或”条件并在那里成功。

于 2014-01-05T23:37:38.243 回答
4
man(X) :-
   setof(t,Y^man(X,Y),_).

除了您要问的内容之外,这还删除了多余的答案/解决方案。

内置setof/3函数在其最后一个参数中描述了在第一个参数中找到的解决方案的排序列表。并且对于目标的自由变量的每个不同实例化。自由变量是那些既不出现在第一个参数中也不作为存在变量出现的变量- 左侧的术语(^)/2

在我们的例子中,这意味着最后一个参数总是[t]无趣的。因此_.

目标中出现的两个变量是XY。或者,更准确地说,包含在X和中的变量YY是一个存在变量。

唯一的自由变量是X。因此,所有解决方案X都被列举出来,没有冗余。请注意,在许多实现中,您不能依赖在这种具体情况下恰好排序的精确顺序。

于 2014-01-06T01:05:59.967 回答