Index: src/java/jedi/functional/FunctionalPrimitives.java =================================================================== --- src/java/jedi/functional/FunctionalPrimitives.java (revision 116) +++ src/java/jedi/functional/FunctionalPrimitives.java Thu Feb 18 14:43:47 GMT 2010 @@ -879,4 +879,13 @@ } return value; } + + public static T first(Collection all, Filter filter) { + for (T t : all) { + if(filter.execute(t)) { + return t; -} + } + } + return null; + } +} Index: src/test/jedi/functional/FunctionalPrimitivesTest.java =================================================================== --- src/test/jedi/functional/FunctionalPrimitivesTest.java (revision 116) +++ src/test/jedi/functional/FunctionalPrimitivesTest.java Thu Feb 18 14:49:23 GMT 2010 @@ -6,45 +6,7 @@ import static jedi.functional.Coercions.asList; import static jedi.functional.Coercions.list; import static jedi.functional.Coercions.set; -import static jedi.functional.FunctionalPrimitives.append; -import static jedi.functional.FunctionalPrimitives.collect; -import static jedi.functional.FunctionalPrimitives.drop; -import static jedi.functional.FunctionalPrimitives.dropRight; -import static jedi.functional.FunctionalPrimitives.flatten; -import static jedi.functional.FunctionalPrimitives.fold; -import static jedi.functional.FunctionalPrimitives.foldPowerset; -import static jedi.functional.FunctionalPrimitives.forEach; -import static jedi.functional.FunctionalPrimitives.group; -import static jedi.functional.FunctionalPrimitives.head; -import static jedi.functional.FunctionalPrimitives.headOption; -import static jedi.functional.FunctionalPrimitives.headOrDefaultIfEmpty; -import static jedi.functional.FunctionalPrimitives.headOrNullIfEmpty; -import static jedi.functional.FunctionalPrimitives.join; -import static jedi.functional.FunctionalPrimitives.last; -import static jedi.functional.FunctionalPrimitives.lastOption; -import static jedi.functional.FunctionalPrimitives.lastOrDefaultIfEmpty; -import static jedi.functional.FunctionalPrimitives.lastOrNullIfEmpty; -import static jedi.functional.FunctionalPrimitives.listTabulate; -import static jedi.functional.FunctionalPrimitives.longest; -import static jedi.functional.FunctionalPrimitives.only; -import static jedi.functional.FunctionalPrimitives.partition; -import static jedi.functional.FunctionalPrimitives.pop; -import static jedi.functional.FunctionalPrimitives.popOption; -import static jedi.functional.FunctionalPrimitives.powerset; -import static jedi.functional.FunctionalPrimitives.produce; -import static jedi.functional.FunctionalPrimitives.reject; -import static jedi.functional.FunctionalPrimitives.reverse; -import static jedi.functional.FunctionalPrimitives.select; -import static jedi.functional.FunctionalPrimitives.sequence; -import static jedi.functional.FunctionalPrimitives.shortest; -import static jedi.functional.FunctionalPrimitives.slice; -import static jedi.functional.FunctionalPrimitives.split; -import static jedi.functional.FunctionalPrimitives.tabulate; -import static jedi.functional.FunctionalPrimitives.tail; -import static jedi.functional.FunctionalPrimitives.take; -import static jedi.functional.FunctionalPrimitives.takeMiddle; -import static jedi.functional.FunctionalPrimitives.takeRight; -import static jedi.functional.FunctionalPrimitives.zip; +import static jedi.functional.FunctionalPrimitives.*; import static jedi.option.Options.none; import static jedi.option.Options.some; @@ -651,4 +613,29 @@ Object returnValue = foldPowerset("a", list("x", "y", "z"), (Functor2) functorMock.proxy()); assertEquals("i", returnValue); } + + @Test + public void firstReturnsTheFirstElementFromTheCollectionMatchingTheFilter() { + List all = list(1,2,3,4); + assertEquals(new Integer(2), first(all, greaterThan(1))); -} + } + + @Test + public void firstReturnsNullIfNoElementMatchesTheFilter() { + List all = list(1,2,3,4); + assertNull(first(all, greaterThan(5))); + } + + @Test + public void firstCanHandleAnEmptyCollection() { + assertNull(first(Collections.EMPTY_LIST, greaterThan(5))); + } + + private Filter greaterThan(final Integer boundary) { + return new Filter(){ + public Boolean execute(Integer value) { + return value > boundary; + } + }; + } +}