ルールを両方向に使う on 7つの言語7つの世界
append(List1, List2, List3)は、List3がList1 + List2のとき真になるらしい。
1 ?- append([oil], [water], [oil, water]).
true.
真偽を確かめる1
2 ?- append([oil], [water], [oil, slick]).
false.
真偽を確かめる2
3 ?- append([tiny], [bubbles], What).
What = [tiny, bubbles].
リストを新規で作成する。
4 ?- append([topping], What, [topping, banana]).
What = [banana].
リストの差分を取る。
5 ?- append(One, Two, [a, b, c]).
One = ,
Two = [a, b, c] ;
One = [a],
Two = [b, c] ;
One = [a, b],
Two = [c] ;
One = [a, b, c],
Two = ;
false.
リストを分割する際のパターンを洗い出す。
これスゲーなマジで!
1つのルールで4つのことが出来てしまうことになるらしい。
これを自前で定義すると以下のようになるそうな
concatenate([], List, List). concatenate([Head|Tail1], List, [Head|Tail2]) :- concatenate(Tail1, List, Tail2).
concatenate([1, 2], [3], What).
Whatには、[1, 2, 3]が入ることを期待する。
1番目のルールにはマッチしないので2番目のルールに当てはめる
concatenate([1 | [2]], [3], [1 |Tail2-A]) :-
concatenate([2], [3], Tail2-A).
Tail2-Aが不明なので、さらにルールを適用(2番目のルール)
concatenate([2 | ], [3], [2 | Tail2-B]) :-
concatenate(, [3], Tail2-B).
Tail2-Bが不明なので、さらにルールを適用(1番目のルール)
concatenate([], [3], [3]).
これでTail2-Bが[3]であることがわかる。
Whatは[1 | 2 | [3]]なので、[1 | [2, 3]]となり、[1, 2, 3]となる。
たった3行で、これすごいけど、相当頭良くないとソラで書けないと思う。
そーゆー意味では、GeneXusっていうウルグアイ生まれのフレームワーク(?)は
業務要件を入力するとJavaやCのソースを自動生成してくれるんだけど
その内部では、Prologが使われているわけで、どんだけすごいコード書いとんねん!
ってことになる。
1 ?- listing. concatenate([], A, A). concatenate([A|B], C, [A|D]) :- concatenate(B, C, D). true. 2 ?- concatenate([oil], [water], [oil, water]). true. 3 ?- concatenate([oil], [water], [oil, slick]). false. 4 ?- concatenate([tiny], [bubbles], What). What = [tiny, bubbles]. 5 ?- concatenate(One, Two, [a, b, c]). One = [], Two = [a, b, c] ; One = [a], Two = [b, c] ; One = [a, b], Two = [c] ; One = [a, b, c], Two = [] ; false.
結果は、標準の(?)appendと同じ動作をする。