Prologでreduce(l|r)

というわけでPrologで書いてみた。

reducel(Pred, [X|List], Result) :-
	reducel(Pred, X, List, Result).
reducel(_, X, [], X).
reducel(Pred, X, [Y|List], Result) :-
	call(Pred, X, Y, Z),
	reducel(Pred, Z, List, Result).

reducer(_, [X], X).
reducer(Pred, [X|List], Result) :-
	reducer(Pred, List, Y),
	call(Pred, X, Y, Result).

20分くらいかかっちゃってます。reducerの方が簡単なんですよね。まだまだPrologは慣れないなぁ。
で、テスト。

?- reducel(pair, [1,2,3,4], R).

R = [[[1, 2], 3], 4] ;

No
?- reducer(pair, [1,2,3,4], R).

R = [1, [2, [3, 4]]] ;

No

大丈夫みたい。pair/3の定義は以下。

pair(X, Y, [X, Y]).

あと、無名関数っぽくかけると楽なので、こんなの書いてみた。

:- op(1150, xfx, =>).
=>(Vars, Term, Arg1, Arg2, Arg3) :-
	copy_term((Vars, Term), (Vs, T)),
	Vs = (Arg1, Arg2, Arg3),
	call(T).

さっきの例はこんな感じになる。

?- reducel((X,Y,Z => Z = [X,Y]), [1,2,3,4], R).

R = [[[1, 2], 3], 4] ;

No
?- reducer((X,Y,Z => Z = [X,Y]), [1,2,3,4], R).

R = [1, [2, [3, 4]]] ;

No

ぜんぜんPrologっぽくないけど気にしない気にしない。