From 510d31b138994bbd629234b173f4243485a463dc Mon Sep 17 00:00:00 2001 From: samskivert Date: Thu, 30 Sep 2010 21:26:26 +0000 Subject: [PATCH] Let's go ahead and add general fold and reduce even though I've held off on adding a function type to samskivert because everyone and their mother has a function type. This is hopefully innocuous enough and allows you to obtain generality at the expense of verbosity: Folds.foldLeft(new Folds.R() { public Integer apply (Integer zero, Integer elem) { return Math.max(zero, elem); } }, 0, values); Folds.foldLeft(new Folds.R() { public String apply (String zero, String elem) { return zero + elem; } }, "", strings); Maybe by Java 8 or 9 we'll have closures and this can become: Folds.foldLeft((Integer b, Integer a) => Math.max(b, a)) Folds.foldLeft((String b, String a) => b + a) or maybe: Folds.foldLeft(#(Integer b, Integer a) { return Math.max(b, a); }) Folds.foldLeft(#(String b, String a) { return b + a; }) who knows where the syntax bike shed arguments will end up. Of course, that'll probably hit the shelves around 2015 or so at the rate Oracle seems to be proceeding. If you really want to get jiggy with the functional programming, you can check out Functional Java, which goes the whole nine yards, but sort of ignores Java's standard collections in the process which kind of sucks: http://functionaljava.org/ git-svn-id: https://samskivert.googlecode.com/svn/trunk@2896 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- src/main/java/com/samskivert/util/Folds.java | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/main/java/com/samskivert/util/Folds.java b/src/main/java/com/samskivert/util/Folds.java index 156331fb..668bcb5a 100644 --- a/src/main/java/com/samskivert/util/Folds.java +++ b/src/main/java/com/samskivert/util/Folds.java @@ -22,6 +22,7 @@ package com.samskivert.util; import java.math.BigInteger; import java.util.Collection; +import java.util.Iterator; import java.util.Map; /** @@ -29,6 +30,42 @@ import java.util.Map; */ public class Folds { + /** Used with {@link #foldLeft}. */ + public interface F + { + /** Folds the supplied element into the result. */ + B apply (B zero, A elem); + } + + /** For reductions and same-typed folds. */ + public interface R extends F {} + + /** + * Left folds the supplied function over the supplied values using the supplied starting value. + */ + public static B foldLeft (F func, B zero, Iterable values) + { + for (A value : values) { + zero = func.apply(zero, value); + } + return zero; + } + + /** + * Reduces the supplied values using the supplied function with a left fold. + * + * @exception NoSuchElementException thrown if values does not contain at least one element. + */ + public static A reduceLeft (F func, Iterable values) + { + Iterator iter = values.iterator(); + A zero = iter.next(); + while (iter.hasNext()) { + zero = func.apply(zero, iter.next()); + } + return zero; + } + /** * Sums the supplied collection of numbers to an int with a left to right fold. */