使用集合时,向集合添加元素的方式如下:
add_to_set(Element, [], [Element]).
add_to_set(Element, [Element | Set], [Element | Set]).
add_to_set(Element, [Element1 | Set], [Element1 | NewSet]) :-
not(Element = Element1),
add_to_set(Element, Set, NewSet).
现在,有了这个,我认为member_of_set就像:
member_of_set(Element, [Element|_]).
member_of_set(Element, [Element1|Set]) :-
not(Element = Element1), /* Not necessary */
member_of_set(Element, Set).
这就像魅力一样,但在这种情况下,not(Element = Element1)
不是必需的。我似乎无法弄清楚为什么。如果您要求Prolog提供更多答案,那么它是否会在member_of_set
的第二个条款中回溯并取得成功?
如果在member_of_set
中没有必要,那么为什么有必要在add_to_set
?
请记住,我只是在Prolog一个月后才开始学习,所以我仍然处于某种心理状态......
我知道使用cut,可能有更好的选择,但不应该使用cut。
答案 0 :(得分:2)
在member_of_set中没有必要
因为如果列表不是一组,它不会受到伤害。只有你最终会 - 如果你传递一个包含重复元素的列表 - 使用多个解决方案,但每个解决方案仍然有效。
OTOH,如果删除测试,add_to_set会导致无效数据:
?- add_to_set(1,[],A),add_to_set(1,A,B).
A = B, B = [1] ;
A = [1],
B = [1, 1] ;
false.
有关剪辑的友好解释,以及为什么在Prolog中有必要,请参阅this page
答案 1 :(得分:1)
contains(Element, [Element|_]).
contains(Element, [_|Set]) :-
contains(Element, Set).
您可以将其读作:“元素在集合中,如果它是该集合的头部,或者它在该集合的尾部”。如果你正在检查它是否在尾部,除了性能原因外,没有必要检查它是否与头部相等。
实际上,通过这种方式,您甚至不会将其限制为Set。它是一般的包含。