计算列表的长度

1
2
3
4
longueur([], 0).
longueur([_|T], N) :-
longueur(T, M),
N is M + 1.
  1. 递归终止条件:
    longueur([], 0). ,当递归到列表中没有元素时,返回 0

  2. 递归计算列表剩余部分的长度
    longueur([_|T], N) :- longueur(T, M), N is M + 1. 这条规则处理的是非空列表的情况。[_|T] 表示一个非空列表,其中 _ 表示列表的头元素(在这里我们并不关心具体是哪个元素,所以用匿名变量 _ 表示),T 是列表的尾(即除了头元素之外的其余元素组成的列表)。

当调用 longueur 谓词来计算非空列表的长度时,首先执行 longueur(T, M)。这是一个递归调用,目的是计算列表 T(即原列表去掉头元素后的剩余部分)的长度,并将结果存储在变量 M 中。通过不断递归调用,每次去掉列表的一个头元素,直到列表为空,此时触发基本情况 longueur([], 0),递归开始回溯。

  1. 计算当前列表的长度
    在递归调用 longueur(T, M) 成功返回后(即已经得到了列表 T 的长度 M),才执行 N is M + 1。因为我们知道,一个非空列表的长度等于它去掉头元素后的剩余部分的长度加 1。所以在得到了列表 T 的长度 M 后,通过 N is M + 1 将当前列表(包含头元素的完整列表)的长度计算出来,并赋值给变量 N

例如,假设有一个列表 [a, b, c],计算其长度的过程如下:

  • 第一次调用 longueur([a, b, c], N),执行 longueur([b, c], M)
  • 第二次调用 longueur([b, c], M),执行 longueur([c], M)
  • 第三次调用 longueur([c], M),执行 longueur([], M),触发基本情况 longueur([], 0),此时 M 被赋值为 0
  • 然后开始回溯,在 longueur([c], M) 中,M0,执行 N is M + 1,得到 N = 1
  • longueur([b, c], M) 中,M1,执行 N is M + 1,得到 N = 2
  • longueur([a, b, c], N) 中,M2,执行 N is M + 1,得到 N = 3,即列表 [a, b, c] 的长度为 3