如何在Prolog中追加列表?

29

如何在Prolog中追加列表?我在互联网上搜索到了这个(取自http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_7.html

append([X|Y],Z,[X|W]) :- append(Y,Z,W).  
append([],X,X).
所以通过从 [X|W] 中删除 [X|Y] 的元素,获得了 Z。但是如何将两个列表连接起来?
例如,
appendlist([1,2],[3,4,5],X).

结果将是 X = [1,2,3,4,5]

我也不知道递归中发生了什么事情。(我追踪了它但不理解)

编辑:我想知道如何编写代码才能像Prolog中预定义的append()函数一样运行。

2个回答

40
您发布的代码(几乎)正确。只需要交换从句的顺序(为了使这个谓词定义在生成方式下具有生产力)即可。
append( [], X, X).                                   % (* your 2nd line *)
append( [X | Y], Z, [X | W]) :- append( Y, Z, W).    % (* your first line *) 

这定义了三个参数之间的关系,假设为ABC
你的第一行表示:“如果AC都是非空列表,并且它们具有相同的(即第一个元素),则C是将AB连接起来的结果,C尾巴是将A的尾部与第二个参数B连接的结果。”
  a        a
  ----------
  b        b
  c        c
  .    d   d
       e   e
       .   .

或者从左到右:

         a | b c .
           |     d e .
         a | b c d e .

append(         [], 
                 Z,
                 Z ).       
append( [X | Y   ],
                 Z,
        [X |         W ] ) :- append(
             Y,  Z,  W).

考虑一下,这是完全有道理的。我们想要定义append/3关系,我们知道它应该是什么,所以我们只需要写下一些我们希望它实现的显而易见的事实,也就是它必须遵循的规则。
假设我们已经为此定义了代码,那么它必须遵循哪些规则呢?显然,将一个列表的尾部与另一个列表连接起来会给我们一个结果列表的尾部,这个结果列表是将原列表与第二个列表连接后得到的。
这定义了我们如何“滑动”第一个列表。但是如果没有更多地方可以滑动怎么办?如果我们已经到达了该列表的末尾怎么办?那么我们就到达了空列表,并且将空列表与另一个列表连接起来会将该列表作为结果返回。这是显而易见的。这就是你的代码中第二行告诉我们的内容,它说,“将一个空列表与另一个列表连接起来会产生该列表作为结果”。
令人惊讶的是,写下append/3必须遵循的这两个规则,与写下定义本身是相同的。

补充:这是从声明性的角度来解释的;请查看m09提供的答案,它更多地从操作的角度来展示。


12

但是我如何将两个列表连接起来呢?

你已经回答了自己的问题:使用append/3

如果你想将XY连接起来并将结果存储在Z中,那么你可以执行以下操作:

append(X, Y, Z)

如果例如X = [1, 2]Y = [3, 4, 5],则Z将绑定到[1, 2, 3, 4, 5]

| ?- append([1,2],[3,4,5], X).

X = [1,2,3,4,5]

yes
| ?- 

1
哦,我的意思是,我该如何编写代码,使其类似于Prolog的append()函数? - Zik
5
你需要按照 append 的编码方式编写它吗?你已经发现了它的实现方式(它是你问题中的前两行代码)。 - aioobe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接