您发布的代码(几乎)没问题。子句的顺序只需要交换(为了使这个谓词定义有效,当以生成方式使用时):
append( [], X, X).                                   % (* your 2nd line *)
append( [X | Y], Z, [X | W]) :- append( Y, Z, W).    % (* your first line *) 
A这定义了三个参数之间的关系,比如说B和C。
你的第一行说,“C是附加的结果,A如果B和A是非C空列表,它们都有相同的头部(即第一个元素),尾部是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 的答案,该答案从操作的角度来看更多。