我用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).
所有这一切都是从列表中提取偶数并将其存储到另一个列表中。 我知道它使用递归工作,但我无法理解执行过程中的步骤。 谁能解释一下?
答案 0 :(得分:2)
该程序包含三个作为一组应用的规则。它们基本上一起工作为if ... else if ... else if ... [else fail]
。
第一条规则是:空列表中的偶数是空列表。这很容易。
如果第一个规则失败(即第一个参数不是空列表),则应用第二个规则。这有点复杂,但基本上说如果是偶数则包含列表的第一个元素。逻辑分解如下。如果右侧的所有条件都为真,那么以H
开头且尾部为T
的列表中的偶数为S
:T
中的偶数是一些列表W
;将Z
除以2之后的H
是余数; Z
为零;并且S
是H
后跟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
,它以相反的顺序返回偶数列表。它颠倒了它并试图将它与包装器中传递的结果统一起来。
辅助方法执行此操作:
但正如@AndréParamés所指出的那样,在调试器中完成它并且它将会变得清晰。