だから、宣言的に読む方法
remove([X|Xs], [X|Ys]) :-
Xs = [_,_|_],
remove(Xs,Ys).
最も重要なことは、:-
実際に何を意味するのかを最初に理解することです。
頭身 :-
_.
それは次のことを意味します: Bodyが保持されているときはいつでも、 Headも保持されていると結論付けることができます。矢印の方向が直感的でないことに注意してください。右から左に進みます。また、何かを結論付けるときに非公式に書かれることが多いように、左から右ではありません。ただし、エラーは、「そこから」得られるものの方向を示しています。
これをよりよく確認するには、Bodyをクエリとして入力します。
?- Xs = [_,_|_], remove(Xs,Ys).
Xs = [A, B],
Ys = [B] ;
Xs = [A, B, C],
Ys = [A, C] ;
...
Xs
したがって、要素が 2 つ未満の場合を除いて、すべての答えが得られます。
手続き的に、物事はまったく逆の方向に起こることに注意してください - そしてそれは初心者にとって非常に混乱します. さらに言えば、Prolog は 2 つの「非伝統的な」機能、時系列バックトラッキングと変数 (実際の変数、すべての可能な用語を意味します) を使用するため、命令型言語や関数型言語でおなじみのこれらのコンパイル時の構成要素ではありません。これらの言語では、変数はランタイム値のホルダーです。具体的な値。Prolog では、実行時にも変数が存在します。詳細については、論理プログラミングと関数型プログラミングの違いを参照してください。
別の問題もありますが、あなたが理解しているかどうかはわかりません。のことを考える:
?- remove(Xs, [1,2]).
Xs = [1, A, 2] ;
false.
ここで何が削除されますか?何もない!まったく逆に、リストにさらに要素を追加しています。このため、この名前remove/2
は Prolog では理想的ではありません。いくつかの引数が与えられ、他の引数が計算されることを強制するコマンド指向プログラミング言語を思い起こさせます。最初は、これは大した問題ではないと思うかもしれません。結局のところ、これはただの名前です。しかし、プログラミングをしていると、すべてを考える時間がないことがよくあることを忘れないでください。したがって、適切なリレーショナル名が望ましい場合があります。
1 つを見つけるには、型だけから始めます: list_list/2
、次に絞り込むlist_removed/2
or list__without_2nd_last/2
。