Prolog 写経記 その 13 insert_last/3

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

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

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

今日は insert_last/3 を写経します.

解説

insert_last(X, List1, List2) は要素 X をリスト List1 の最後に挿入した新しいリストを List2 として返す.

ふむ.Java でいうと List#add(Object) みたいな.

モード

insert_last(?, ?, ?)

ふむふむ.
と書いてあるのだけど,実際は違うんじゃないかと思う今日この頃.
違うってのは言い過ぎかもしれないけれど,本当はこういう事なんじゃなかろうか?

insert_last(+, +, +)
insert_last(+, +, -)
insert_last(+, -, +)
insert_last(-, +, +)
insert_last(-, -, +)

これで全部じゃないかもしれないけれど.
ともあれ (JW),こういう組み合わせを把握しておかないと,insert/4 みたいに無限ループに陥ることもあるわけで...
でもでも,こういうのを全部挙げてたらきりがないよなぁ.

定義

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

insert_last(X, List1, List2) :-
	conc(List1, [X], List2).

なんというか...
手抜きに感じるのは私だけ? (^^;
いや,決して手抜きなんて事はないんでしょうけど...
なんか拍子抜けだなぁ.
っていうか,conc/3 って List1 の要素数分だけ再帰するんだよね.たった一つ要素を付け加えるのに要素数再帰するってなんかいやーん.末尾再帰最適化してくれると信じて気にしないのが吉ですかそうですか.

注記

List2 が具体化され X が具体化されていない場合,insert_last/3 は与えられたリストの最後の要素を返す.つまり last/2 と同じ働きをする.

らじゃあ.

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

2 ?- insert_last(circle, [square, triangle], L).

L = [square, triangle, circle] 

Yes
3 ?- insert_last(X, _, [a-c, c+b, d-a, a+b]).

X = a+b 

Yes

ふむ.
最後の例では第 2 引数を無名変数にしているけれど,ちゃんとした変数にしても大丈夫なはず.

4 ?- insert_last(X, Y, [a, b, c]).

X = c
Y = [a, b] 

Yes

ふむ.
特にどうという事もないわけなので,しょうがないから例によっていぢわる.

5 ?- insert_last(X, Y, Z).

X = _G308
Y = []
Z = [_G308] ;

X = _G308
Y = [_G393]
Z = [_G393, _G308] ;

X = _G308
Y = [_G393, _G399]
Z = [_G393, _G399, _G308] ;

X = _G308
Y = [_G393, _G399, _G405]
Z = [_G393, _G399, _G405, _G308] ;

X = _G308
Y = [_G393, _G399, _G405, _G411]
Z = [_G393, _G399, _G405, _G411, _G308] ;

・
・
・

やはり.
もう一つ.

6 ?- insert_last(a, X, Y).

X = []
Y = [a] ;

X = [_G378]
Y = [_G378, a] ;

X = [_G378, _G384]
Y = [_G378, _G384, a] ;

X = [_G378, _G384, _G390]
Y = [_G378, _G384, _G390, a] ;

X = [_G378, _G384, _G390, _G396]
Y = [_G378, _G384, _G390, _G396, a] ;

・
・
・

やはり.
最後に.

7 ?- insert_last(X, [a, b, c], Y).

X = _G365
Y = [a, b, c, _G365] ;

No

あら?
これはちょっと予想外.こっちも延々繰り返すかと思ったのですが.
ともあれ (JW),ちゃんと動く引数の組み合わせは「モード」で「本当はこういうこと」と書いた通りでよさげ.