投稿したコードは(ほぼ)OKです。節の順序を入れ替える必要があります(生成的な方法で使用される場合、この述語定義を生産的にするために):
append( [], X, X). % (* your 2nd line *)
append( [X | Y], Z, [X | W]) :- append( Y, Z, W). % (* your first line *)
A
これは、3つの引数、たとえば、、B
との間の関係を定義しますC
。
最初の行は、「C
追加の結果でA
ありB
、A
とC
が空でないリストの場合、両方とも同じヘッド(つまり、最初の要素)を持ち、の末尾は、同じ2番目の引数で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
どうなりたいかを知っているので、私たちがそれを実現したいといういくつかの明白な事実、あなたがそうするなら従わなければならない法則を書き留めます。
したがって、このコードがすでに定義されていると仮定すると、どのような法律に従う必要がありますか?明らかに、あるリストの末尾に別のリストを追加すると、完全なリストにその2番目のリストを追加した結果の末尾が得られます。
これは、最初のリストを「スライド」する方法を定義します。しかし、スライドする場所がこれ以上ない場合はどうなりますか?そのリストの最後に達した場合はどうなりますか?次に、空のリストに到達しました。空のリストに別のリストを追加すると、結果としてそのリストが得られます。明らかに。そして、それはあなたのコードのその2行目が私たちに伝えていることであり、「空のリストを別のリストに追加すると、結果としてそのリストが生成されます」と書かれています。
驚くべきことに、append/3
従わなければならないこれら2つの法則を書き留めたことは、定義自体を書き留めることと同じです。
さらに、これは宣言的な観点から説明します。運用の観点からより多くを示しているm09による回答をチェックしてください。