Edited at

# Prologでfor-loop

More than 3 years have passed since last update.

Prologでfor-loopを回す方法を紹介します。

ついでにPythonとの比較も付けてみました。

# 基礎編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: リストの中身を処理して別のリストに格納

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で処理する

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を回す毎に新たな述語が増えてしまうのはちょっと・・・。

このへんのリスト処理については汎用的な述語を作っておくと便利かもしれませんね。