Prologでfor-loop

  • 0
    いいね
  • 2
    コメント
    この記事は最終更新日から1年以上が経過しています。

    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を回す毎に新たな述語が増えてしまうのはちょっと・・・。
    このへんのリスト処理については汎用的な述語を作っておくと便利かもしれませんね。