Prologでfor-loopを回す方法を紹介します。
ついでにPythonとの比較も付けてみました。
利用したProlog処理系: AZ-Prolog 7.54
基礎編1: リストの要素を順に出力する
python
>>> my_list = [1, 2, 3, 4, 5]
>>> for x in my_list:
>>> print x
...
1
2
3
4
5
prolog
print_list([]).
print_list([Element|List]):-
write(Element),nl,
print_list(List).
?- print_list([1,2,3,4,5]).
1
2
3
4
5
yes
基礎編2: リストの中身を処理して別のリストに格納
例えば、リストの中身を2倍する場合。
python
>>> my_list = [1, 2, 3, 4, 5]
>>> new_list = []
>>> for x in my_list:
>>> new_list.append(x * 2)
...
>>> new_list
[2, 4, 6, 8, 10]
もしくはリスト内包表記で、
python
>>> new_list = [x * 2 for x in my_list]
prolog
twice_list(OldList,NewList):-
twice_list(OldList,[],NewList).
twice_list([],NewListRev,NewList):-
reverse(NewListRev,NewList).
twice_list([OldNum|OldList],TempList,NewList):-
NewNum is OldNum * 2,
twice_list(OldList,[NewNum|TempList],NewList).
?-OldList=[1,2,3,4,5],twice_list(OldList,NewList).
NewList = [2,4,6,8,10]
yes
もしくは差分リストを利用して、
prolog
twice_list2(OldList,NewList):-
twice_list2(OldList,TempList-TempList,NewList).
twice_list2([],NewList-[],NewList).
twice_list2([OldNum|OldList],List-[NewNum|Tail],NewList):-
NewNum is OldNum * 2,
twice_list2(OldList,List-Tail,NewList).
?-OldList=[1,2,3,4,5],twice_list2(OldList,NewList).
NewList = [2,4,6,8,10]
yes
応用編: 条件をつけてfor-loopで処理する
例えば、偶数の時のみ2倍する場合。
python
>>> my_list = [1, 2, 3, 4, 5]
>>> new_list = [x * 2 if x % 2 == 0 else x for x in my_list]
>>> new_list
[1, 4, 3, 8, 5]
prolog
twice_even_number(OldList,NewList):-
twice_even_number(OldList,TempList-TempList,NewList).
twice_even_number([],NewList-[],NewList).
twice_even_number([OldNum|OldList],List-[NewNum|Tail],NewList):-
Rest is OldNum mod 2,
Rest = 0,
NewNum is OldNum * 2,
twice_even_number(OldList,List-Tail,NewList).
twice_even_number([OldNum|OldList],List-[OldNum|Tail],NewList):-
twice_even_number(OldList,List-Tail,NewList).
?-OldList=[1,2,3,4,5],twice_even_number(OldList,NewList).
NewList = [1,4,3,8,5]
yes
感想
Pythonのシンプルさを再実感しました。
Prologはfor-loopを回す毎に新たな述語が増えてしまうのはちょっと・・・。
このへんのリスト処理については汎用的な述語を作っておくと便利かもしれませんね。