Prolog中的递归和列表

列表在Prolog中添加实现 –

append([],X,X). 
append([H|T1],X,[H|T2]) :- 
    append(T1,X,T2).

给出了 –

append([a,b,c],[d,e,f],X). 

输出 –

X = [a,b,c,d,e,f].

我想知道它是如何工作的,我试图跟踪函数调用,但我不明白T2,这是一个列表的尾部,可以作为X的尾部附加([a,b,c],[ d,e,f],X)呼叫尚未定义.
你可以为我清理这个递归吗?

最佳答案 它归结为统一在Prolog中如何运作.基本上:

>原子只有在相同时才统一起来
>变量与任何东西统一
>化合物在每种成分统一时统一起来

所以你打电话:追加([a,b,c],[d,e,f],Y)这是你的第一个目标.请注意,为了便于查看,我将变量名称从X更改为Y.

这必须与事实或规则统一:让我们看看它是否会与追加([],X,X)统一?

      (1)  append([a, b, c], [d, e, f], Y)
      (2)  append([], X, X)

(1)和(2)都有相同的仿函数(追加),所以这很好,它们都有3个参数,所以这也很好.但统一每个相应的论点必须统一起来.因此,(1)中的第一个列表[a,b,c]将尝试与(2)中的空列表统一,但它们不能,因为(1)中的列表不是空列表.所以统一失败了.

然后我们可以尝试用append([H | T1],X,[H | T2])来统一.

      (1)   append([a, b, c], [d, e, f], Y)
      (2)   append([H|T1],X,[H|T2])

这次(1)中的列表[a,b,c]将尝试与(2)中的列表[H | T1]统一.为了使这成为可能,变量H可以与原子a(H – > a)结合,并且列表T1可以与(1)中的列表的尾部绑定,T1 – > [b,c].所以第一个论点的作用就是我们所拥有的:

      (1)   append([a, b, c], [d, e, f], Y)
      (2)'   append([a, b, c],X,[a|T2])

第二个参数也将统一,因为X是一个变量并将绑定到任何东西. X – > [d,e,f]所以我们有:

      (1)   append([a, b, c], [d, e, f], Y)
      (2)''   append([a, b, c],[d, e, f],[a|T2])

最后,最后一个论点统一起因为Y – > [A | T 2].所以现在它与规则的头部统一起来,我们需要弄清楚规则的主体:我们现在最终将追加([b,c],[d,e,f],T2)作为目标.

从第一个事实开始,我们再次查找此目标将绑定的子句.通过上面的相同解释,它将不与第一个条款统一,但将与具有绑定的第二个统一:H – > b,T1 – > [c],X – > [d,e,f]和T2 – >并[b | T2′ ].

我们留下了目标:追加([c],[d,e,f],T2′).同样,它不与第一个子句统一,并与第二个与绑定结合:H – > c,T1 – > [],X – > [d,e,f],T2′ – >并[c | T2 ”].

现在的目标是:追加([],[d,e,f],T2”).

让我们看看当我们尝试将第1条与第1条统一时会发生什么:

     (1)   append([], [d, e, f], T2'')
     (2)   append([],X,X)

两个空列表统一,X – > [d,e,f]并且由于T2” – > X,然后是T2” – > [d,e,f].现在,棘手的部分是跟踪到目前为止的递归调用,现在沿着递归返回以查看最终结果.回想起T2′ – > [c | T2”]所以T2’实际上是[c,d,e,f].并回想起T2 – > [B | T2′]所以T2实际上是[b,c,d,e,f].

最后Y – > [a | T2]因此Y是[a,b,c,d,e,f].由于Y是外部变量,因此现在显示原始目标已满足.

点赞