Prolog 写経記 その 28 split_all/3

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

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

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

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

解説

split_all(Del, List, Lists)List を分割し Lists とする.Del は敷居として用いられ, Lists 中には現れない.

ふむ.Java でいうと... リストじゃないけど近いのは String#split(String) かな.正規表現だけど.

モード

split_all(+, +, ?)

珍しく使い方が限定された述語ですね.

定義

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

split_all(Del, [Del], [[], []]) :-
	!.
split_all(Del, List, [X | Lists]) :-
	conc(X, [Del | Y], List),
	!,
	split_all(Del, Y, Lists).
split_all(_, List, [List]).

むむぅ...
一見してごちゃごちゃした感じですが,実はいつものパターン.
List をデリミタ Del とその右の要素からなるリストと左の要素からなるリストに分けて,左の要素を再帰的に分けて,それらをくっつけてます.


微妙なのは停止条件となる最初の節.
デリミタだけからなるリストを分割した結果は空リスト二つを要素とするリスト?? なぜ??
...
そうか,デリミタの左右に空リストがあると考えるわけかぁ.なんか微妙.

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

2 ?- split_all(x, [i, x, j, k, x, l, x], L1).

L1 = [[i], [j, k], [l], []] 

Yes
3 ?- split_all(z, [a, b, c, d], L2).

L2 = [[a, b, c, d]] 

Yes
4 ?- split_all(0, [0, 0, 0], L3).

L3 = [[], [], [], []] 

Yes

ふむ.
最後の例,デリミタ 3 つからなるリストを分割すると空リスト 4 つからなるリストになってます.
定義のところで見たように,デリミタの周囲に空リストがあるという考え方のようですが,ちょっと直感的じゃない感じ.
うーみゅ...