前の記事で、語とカテゴリのリストのことを書いたが、このリストから語だけを全て取り出すprologのルールをほぼ1日かけて作成した。単純なはずなのだが、なかなかうまくいかなかった。また、prologというものに、完全に馴染んでいないからだと思う。普通のc, java, pythonなどと、プログラムの考え方が、全く異なっているのだから。
ルールは、次のようになる。 %で、始まる行はコメントである。
%% headがアトムの場合、tailから取り出したものと結合する %% 特殊な二分木なので、tailに複雑に構造化されたリストはあり得ない %% atomか[a,b]の形のものしか、tailの要素にはならないのだ getlist([H|[T]],[H,H1]) :- atom(H),[H1|_] = T,!. %% headがatomならば、それを取り出す getlist([H|[_]],H) :- atom(H),!. %% tailがatomの場合:その場合でも、headからは、必ず1個以上のatomが該当する getlist([H|[T]],[Z,T]) :- atom(T),getlist(H,Z),!. %% 残されたのは、headもtailもリストの場合 getlist([H|[T]],[X1, X2]) :- getlist(H,X1),getlist(T,X2).
これをswi-prologで。いくつかの場合に適応してみた例が以下のものである。
1 ?- [user]. |: getlist([H|[T]],[H,H1]) :- atom(H),[H1|_] = T,!. |: getlist([H|[_]],H) :- atom(H),!. |: getlist([H|[T]],[Z,T]) :- atom(T),getlist(H,Z),!. |: getlist([H|[T]],[X1, X2]) :- getlist(H,X1),getlist(T,X2). |: ^D % user://1 compiled 0.00 sec, 4 clauses true. 2 ?- getlist([a,b],X). X = a. 3 ?- getlist([a,[b,c]],X). X = [a, b]. 4 ?- getlist([[[a,b],[c,d]],[e,f]],X). X = [[a, c], e]. 5 ?- getlist([[a,b],[c,d]],X). X = [a, c]. 6 ?- getlist([[a,b],c],X). X = [a, c]. 7 ?- getlist([[[下, '場所-機能'], [人, 人]],[菓子, '人工物-食べ物']],X). X = [[下, 人], 菓子]. 8 ?-
最初は、ルールを[user].で読み込ませているところで、2 以降が実行結果である。4でリストが二重になっているところが気になる他は、きちんと頭を取り出して、リストにしている。7は、前の記事での例を実行させたもので、カテゴリを除く語だけ取り出していることが理解できるだろう。
ただし、すべての場合を尽くしていないので、不都合が現れるかもしれない。