インタビューの質問!
これは通常、Prologでmember
関係を定義する方法です。
member(X, [X|_]). % member(X, [Head|Tail]) is true if X = Head
% that is, if X is the head of the list
member(X, [_|Tail]) :- % or if X is a member of Tail,
member(X, Tail). % ie. if member(X, Tail) is true.
1つのルールのみを使用して定義します。
解決:
_member(X, [Y|T]) :- X = Y; member(X, T).
_
デモンストレーション:
_?- member(a, []).
fail.
?- member(a, [a]).
true ;
fail.
?- member(a, [b]).
fail.
?- member(a, [1, 2, 3, a, 5, 6, a]).
true ;
true ;
fail.
_
使い方:
[Y|T]
_で最初の引数X
の出現を探しています。Y
は頭に一致し、T
は尾に一致します。X = Y
_(つまり、X
をY
と統合できる)の場合、リストにX
が見つかりました。そうでなければ(_;
_)X
が末尾にあるかどうかをテストします。備考:
=
_(統一)を使用すると、_==
_(同等性のテスト)を使用するよりも柔軟なコードが生成されることを指摘してくれた humble coffee に感謝します。このコードは、特定のリストの要素を列挙するためにも使用できます。
_?- member(X, [a, b]).
X = a ;
X = b ;
fail.
_
また、特定の要素を含むすべてのリストを「列挙」するために使用できます。
_?- member(a, X).
X = [a|_G246] ;
X = [_G245, a|_G249] ;
X = [_G245, _G248, a|_G252] ;
...
_
上記のコードで_=
_を_==
_に置き換えると、柔軟性が大幅に低下します。member(X, [a])
ですぐに失敗し、member(a, X)
でスタックオーバーフローが発生します(テスト済み) SWI-Prologバージョン5.6.57)。
使用を許可されている他の述語を指定しなかったので、少しだましてみます。 :P
member(X, L) :- append(_, [X|_], L).
newmember(X, Xs) :-
phrase(( ..., [X] ),Xs, _).
と
... --> [] | [_], ... .
実際、次の定義は、Xs
がリストであることも保証します。
member_oflist(X, Xs) :-
phrase(( ..., [X], ... ), Xs).
上記の...
の定義の最初の出現は、pです。 205、注1の
David B. Searls、定型文法によるDNAの言語学の調査。 NACLP 1989、第1巻。