Prolog - 这个程序如何工作

时间:2011-05-26 00:48:27

标签: prolog

我用prolog语言编写了这个程序。 问题是我无法理解它是如何工作的。

even_number([],[]).
even_number([H|T],S):-even_number(T,W),Z is H mod 2,Z==0,S=[H|W].
even_number([_|T],S):-even_number(T,S).

所有这一切都是从列表中提取偶数并将其存储到另一个列表中。 我知道它使用递归工作,但我无法理解执行过程中的步骤。 谁能解释一下?

2 个答案:

答案 0 :(得分:2)

该程序包含三个作为一组应用的规则。它们基本上一起工作为if ... else if ... else if ... [else fail]

第一条规则是:空列表中的偶数是空列表。这很容易。

如果第一个规则失败(即第一个参数不是空列表),则应用第二个规则。这有点复杂,但基本上说如果是偶数则包含列表的第一个元素。逻辑分解如下。如果右侧的所有条件都为真,那么以H开头且尾部为T的列表中的偶数为ST中的偶数是一些列表W;将Z除以2之后的H是余数; Z为零;并且SH后跟W(无论W原来是什么)。 (请注意,如果将第一个术语移至测试Z==0之后,此规则将更有效。)

如果该规则失败(即H为奇数),则应用最后一条规则:列表中的偶数是列表尾部的偶数。

答案 1 :(得分:0)

它的写得很差。如果你重构它并使其尾递归,可能会更容易理解:

even_numbers( X , R ) :-
  even_numbers( X , [] , T ) ,
  reverse( T , R ).

even_numbers( [] , T , T ).
even_numbers( [X|Xs] , T , R ) :-
  Z is X mod 2 ,
  Z == 0 ,
  ! ,
  even_numbers( Xs , [X|T] , R ).
even_numbers( [_|Xs] , T , R ) :-
  even_numbers( Xs , T , R ).

第一个谓词even_numbers/2谓词是公共包装器。它调用私有帮助器even_numbers/3,它以相反的顺序返回偶数列表。它颠倒了它并试图将它与包装器中传递的结果统一起来。 辅助方法执行此操作:

  • 如果源列表为空:将累加器(T)与结果统一。
  • 如果源列表不为空,并且列表(X)的头部是偶数,
    • 递减列表的尾部(Xs),将X推到累加器上。
  • 如果源列表不为空,并且列表(X)的头部是奇数,
    • 在不修改累加器的情况下递归列表尾部(Xs)。

但正如@AndréParamés所指出的那样,在调试器中完成它并且它将会变得清晰。