ここにバグがあります:
member(X,[X|T]) :- member(X,T).
あなたが実際に言っていることは(あなたが言っていると思うこととは対照的に)member/2
、Xがリストの先頭にあり、リストの末尾にある場合に当てはまります。この述語は、リストの先頭にある同じものの最初のN個のコピーにのみ当てはまるので、言うのは非常に奇妙なことです。
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
これで、次のような操作を行うことで、バグを修正してもシングルトン警告を表示できます。
member(X, [Y|T]) :- member(X, T).
しかし、これは、2つのヘッドを使用する従来の定義や、明示的なORを使用する@CapelliCのバージョン(+1)ほど良くありません。私は、Prologをもう少しよく理解するまで待ってから、Prologコードの美学の意味で多くのストックを置くべきだと思います。しばらくそれを続けると、この警告と匿名変数の使用に感謝するようになります。
Prologでシングルトン変数を役に立たないものにしているのは、それらに名前が付けられているが、それらについて何も知られていないことと、残りの計算に影響を与えないことです。アンダースコアは、意味に影響を与えることなく、絶対に何でもそこに入ることができることを強調しています。何が
member(X, [X|T]).
本当は、Xが位置1であり、位置2のリストの先頭にあるXと同じであるということです。リストは空であるか、先頭と末尾が必要ですが、末尾にあるものはここでは関係ありません。重要なのはそのXは頭でもあります。Tはリストの残りの部分であるか、不適切なリストであるか、ブレッドボックス、稲妻、または春の日の空気の匂いである可能性があります。の真実とは何の関係もありませんmember(X, [X|T])
。
シングルトン警告は、「ここで何かの名前を予約しましたが、その名前で何かを呼び出すことはありません」と通知します。このメッセージを受け取ったときに最初に行うことは、明らかなタイプミスではありませんが、名前を_に置き換えて、コードがまだ意味があるかどうかを確認することです。そうでない場合は、論理エラーがあります。もしそうなら、それはおそらく不要でした。