fold - fold([lr]1?)?, reduce, Aggregate, accumulate

http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29

Common Lispにはreduceという関数があり、これはSchemeHaskellでいうところのfoldにあたります。
いわゆる畳み込み関数というやつで、『畳み込みする関数』と『その初期値』を使って、リストを1要素に集約します。これを使うとSUM関数を簡単に定義できます。

上記Wikipediaからの転載ですが、こんなのもあるのねえ、ということで各言語ごとリストアップ。

Common Lisp
(reduce #'func list :initial-value init-value)
Python2.5
reduce
JavaScript1.8
.reduce(func, init) もちろんIEでは使えず。まあ、定義すりゃあいけるんですが。
Ruby
inject, reduce
Haskell
fold{l|r} 型がちゃんとしているのが気持ちいい。
Erlang
foldl, foldrで存在。
OCaml
fold_{left|right}
C++
std::accumulate(). 自分の環境では発見できなかった orz
C#3.0
.Aggregate(init, func)

Javaにないorz

きっとApache Commonsを探せばあるんでしょうけど、Java自体には無かった。

きっとJava7~9ぐらいのLambdaサポートで出てくるんでしょうけれども。

まあ、それはそれとして。適当に作ってみる。

まず集約関数のインタフェースを定義します。*1

public interface Aggregator<L, R> {
	R aggregate(L l, R r);
}

次に集約メソッドを定義します。まあ、ジェネリック型定義はこんなもんで妥当っぽいでしょう。

public class FoldImplementation {

	/**
	 * {@link Iterable}を集約します。ま、別に{@link java.util.Iterator}を集約してもいいんだけど。
	 * 
	 * @param <L>
	 *            集約されるリスト({@link Iterable})の型
	 * @param <R>
	 *            集約後(あるいは集約初期値)の型
	 * @param func
	 *            畳みこみする関数
	 * @param list
	 *            集約対象リスト
	 * @param init
	 *            集約時の初期値
	 * @return 集約結果
	 */
	public static <L, R> R foldl(final Aggregator<? super L, R> func,
			final Iterable<? extends L> list, final R init) {
		R aggregated = init;
		for (final L each : list) {
			aggregated = func.aggregate(each, aggregated);
		}
		return aggregated;
	}

}

動かしてみよう。ということで積をとってみます。

import java.util.ArrayList;

public final class Main {
	public static void main(String[] args) {
		int init = 1;
		Aggregator<Integer, Integer> product = new Aggregator<Integer, Integer>() {
			@Override
			public Integer aggregate(Integer l, Integer r) {
				return l * r;
			}
		};
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(12);
		list.add(34);
		list.add(56);
		list.add(78);
		list.add(90);

		final int result = FoldImplementation.foldl(product, list, init);
		System.out.println(result); // 160392960
	}
}

*1:1メソッドのインタフェースの乱発ってオブジェクト指向に反してる??