如果Element和Element1不同,为什么我不需要检查member_of_set?

时间:2013-11-26 20:30:00

标签: prolog

使用集合时,向集合添加元素的方式如下:

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。

2 个答案:

答案 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。它是一般的包含。