我有以下问题:
prolog prog:
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”是否被初始化,如果是,而不是“一次......”,否则......那样的话:
man(Man) :- (->check<-,once(man(Man, _)); man(Man, _).
在“检查”上应该是用于检查变量“Man”是否已填充的代码。
这可能吗?
答案 0 :(得分:4)
实现这一目标的一种方法如下:
man(X) :-
(nonvar(X), man(X, _)), !
;
man(X, _).
或者,更优选的是:
man(X) :-
( var(X)
-> man(X, _)
; once(man(X, _))
).
剪切将确保只有一个解决方案(最多)到实例化的X
,而非实例化的情况将继续运行。请注意,通过剪切,您不需要once/1
。 once/1
如果没有削减就无法正常工作的原因是回溯仍然会回来并采取“或”条件并在那里取得成功。
答案 1 :(得分:4)
man(X) :-
setof(t,Y^man(X,Y),_).
除了您的要求之外,这还删除了多余的答案/解决方案。
内置setof/3
在其最后一个参数中描述了在第一个参数中找到的解决方案的排序列表。并且为每个不同的实例化目标的自由变量。
自由变量既不是第一个参数也不是存在变量 - (^)/2
左侧的术语。
在我们的例子中,这意味着最后一个参数将永远是[t]
,这是无趣的。因此_
。
目标中出现的两个变量是X
和Y
。或者,更准确地说,X
和Y
中包含的变量。 Y
是一个存在变量。
唯一的自由变量是X
。所以X
的所有解决方案都是在没有冗余的情况下枚举的。请注意,在许多实现中,您不能依赖于在具体情况下正好排序的精确顺序。