2011-05-26 25 views
2

我有用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

Ted的回答很好,但是尝试将该程序保存到文件中,启动一个prolog解释器,加载程序('[filename] .'),开始跟踪(使用trace.'),然后调用'even_number'统治与清单。在试图了解它的工作原理时,逐步看到它的执行是非常有用的。 – 2011-05-26 01:15:11

回答

2

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

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

如果第一个规则失败(即第一个参数不是空列表),则应用第二个规则。这有点复杂,但基本上说包含列表的第一个元素,如果它是偶数。逻辑分解如下。以H开头且尾部为T的列表中的偶数为S如果右侧的所有项均为真:T中的偶数为某个列表W; Z是将H除以2后的余数;那Z是零;那SH其次是W(不管W竟然是)。 (请注意,如果第一项移至Z==0后,此规则将更有效。)

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

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)的尾部,而无需修改累加器。

但正如@安德烈Paramés指出,通过它在调试工作,便清楚发生了什么事情。