Prolog 写経記 その 32 substitute_all/4

(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.

Prologユーティリティライブラリ

Prologユーティリティライブラリ

今日は substitute_all/4 を写経します.

解説

substitute_all(X, Y, List1, List2)List1 に現れる要素 X のすべてを Y に変更した新しいリストを List2 として返す.

ふむ.Java でいうと今度こそ Collections#replaceAll(List, Object, Object) ですね.

モード

substitute_all(?, ?, ?, ?).

おっと,今度は全ての変数が入出力両用に.

定義

では,こいつの定義を写経しませう.

substitute_all(_, _, [], []).
substitute_all(X, Y, [X | List1], [Y | List2]) :-
	X \== Y, !,
	substitute_all(X, Y, List1, List2).
substitute_all(X, Y, [Z | List1], [Z | List2]) :-
	substitute_all(X, Y, List1, List2).

さすがに今回は conc/3 を使っていませんね.
2番目の節に出てくる \== は両辺のリテラルが一致しない場合に成功する組み込み述語らしい.
普通の = は比較演算子というより同一化するという意味合いが強くて,

2 ?- X = a, X = Y.

X = a
Y = a 

Yes

となるのに対して,== だと

3 ?- X = a, X == Y.

No

と,こっちの方は具体化された値が等しいかどうかをチェックする模様.
\=\== はそれぞれの否定.


ともあれ (JW),2 番目の節は第 3 引数で与えられたリストの先頭の要素が X と一致した場合に第 4 引数で与えられたリストの先頭の要素を Y にするわけですね.
3 番目の節は第 3 引数で与えられたリストの先頭の要素が X と一致しなかった場合はそのまま〜ってこと.特にガードが入ってないけど 2 番目の節にカットが付いているから一致した場合ここには来ない,と.

では使用例を写経しませう.

4 ?- substitute_all(0, 1, [1, 0, 1, 0, 0], L).

L = [1, 1, 1, 1, 1] 

Yes
5 ?- substitute_all(x, y, [t, v, z], Y).

Y = [t, v, z] 

Yes

6 ?- substitute_all(X1, X2, [b, a, c, a, d], [b, d, c, d, d]).

X1 = a
X2 = d 

Yes
7 ?- substitute_all(1, 2, List, [3, 2, 4, 2 ,5]).

List = [3, 1, 4, 1, 5] 

ふむ.
まぁこんな感じだよねぇ.うんうん.