Prolog返回列表的递归谓词check_list运行逻辑咨询
check_list 谓词运行机制讲解 结合你已经理解的divides和find_num逻辑,整个程序的效果是输入整数X、Y,返回1到X范围内所有能被Y整除的整数组成的列表,其中核心的列表筛选逻辑完全由check_list实现。
Prolog的谓词会按照子句的书写顺序从上到下匹配,匹配成功就执行子句内的逻辑,匹配失败则自动回溯尝试下一个子句,check_list的三个子句分别对应递归处理列表的三种情况:
- 第一个子句
check_list([], _, []).
这是递归终止的基线条件:当输入的待处理列表为空时,不管Y是什么值,输出的结果列表必然为空,递归走到这一步就终止,不再向下调用。 - 第二个子句
check_list([H | Tin], Y, [H | Tout]) :- divides(H, Y), check_list(Tin, Y, Tout).
这是满足筛选规则的处理分支:首先把待处理列表拆分为队首元素H和剩余列表Tin,如果H能被Y整除(即divides(H,Y)成立),就把H保留在结果列表的头部,剩下的结果内容Tout,通过递归处理剩余列表Tin得到。 - 第三个子句
check_list([H | Tin], Y, Lout) :- \+ divides(H, Y), check_list(Tin, Y, Lout).
这是不满足筛选规则的处理分支:如果当前队首元素H不能被Y整除(\+是Prolog的否定运算符,表示后面的目标不成立),就直接丢弃H,不放入结果列表,最终的结果Lout完全由剩余列表Tin递归处理得到。
实际执行流程示例
以调用 check_list([1,2,3,4,5,6], 2, Res) 为例,完整执行步骤如下:
- 初始待处理列表为
[1,2,3,4,5,6],队首H=1,判断divides(1,2):1 mod 2结果为1,不满足整除条件,第二个子句匹配失败,走第三个子句丢弃1,递归处理剩余列表[2,3,4,5,6] - 待处理列表变为
[2,3,4,5,6],队首H=2,divides(2,2)成立,走第二个子句将2放入结果,递归处理剩余列表[3,4,5,6] - 待处理列表变为
[3,4,5,6],队首H=3,divides(3,2)不成立,丢弃3,递归处理剩余列表[4,5,6] - 待处理列表变为
[4,5,6],队首H=4,divides(4,2)成立,将4放入结果,递归处理剩余列表[5,6] - 待处理列表变为
[5,6],队首H=5,divides(5,2)不成立,丢弃5,递归处理剩余列表[6] - 待处理列表变为
[6],队首H=6,divides(6,2)成立,将6放入结果,递归处理空列表[] - 待处理列表为空,命中第一个基线条件返回空列表,逐层向上拼接之前保留的2、4、6,最终得到结果
Res = [2,4,6]
这种写法是Prolog中处理列表过滤的经典递归范式,逻辑和其他函数式编程语言中的filter函数完全一致。
内容的提问来源于stack exchange,提问作者NewCoder
相关产品推荐
相关产品推荐

