Does A Collection Contain an Item With a Property of a Particular Value?
This example uses FirstOrderLogic.exists(java.util.Collection, Filter).
Conventional Java
... public Bar getBar() { return bar; } ...
... public boolean containsFooWithBar(Bar requiredBar) { Iterator<Foo> iter = foos.iterator(); while (iter.hasNext()) { Foo foo = iter.next(); if (foo.getBar().equals(requiredBar)) { return true; } } return false; } ...
Jedi Java
// Annotate the accessor @JediFilter public Bar getBar() { return bar; } ...
... public boolean containsFooWithBar(Bar requiredBar) { return exists(foos, getBarEqualsFilter(requiredBar)); } ...
The getBarEqualsFilter method was generated by the @JediFilter annotation and statically imported.
Select All Items From a Collection Where The Item's Property Matches a Given Value
This example uses FunctionalPrimitives.select(java.util.Collection, Filter).
Conventional Java
Conventional Foo.java as in previous example.
... public List<Foo> getFoosWithBar(Bar requiredBar) { List<Foo> matching = new ArrayList<Foo>(); Iterator<Foo> iter = foos.iterator(); while (iter.hasNext()) { Foo foo = iter.next(); if (foo.getBar().equals(requiredBar)) { matching.add(foo); } } return matching; } ...
Get The Values of A Property For All Items In A Collection
This example uses FunctionalPrimitives.collect(java.util.Collection, Functor).
Quick Sort
This example uses:
- FunctionalPrimitives.append(java.util.Collection<? extends T>... collections)]
- FunctionalPrimitives.head(java.util.Collection)]
- FunctionalPrimitives.list(T... items)
- FunctionalPrimitives.select(java.util.Collection, Filter)
- Comparables.lessThan(T, java.util.Comparator<T>)
- Comparables.greaterThan(T, java.util.Comparator<T>)
Conventional Java
public <T> void qsort(T[] collection, Comparator<T> comparator, int lo, int hi) { int h, l, p, t; if (lo < hi) { l = lo; h = hi; p = collection[hi]; do { while ((l < h) && (comparator.compareTo(collection[l], p) < 0)) { l = l+1; } while ((h > l) && (comparator.compareTo(collection[h], p) >= 0)) { h = h-1; } if (l < h) { t = collection[l]; collection[l] = collection[h]; collection[h] = t; } } while (l < h); t = collection[l]; collection[l] = collection[hi]; collection[hi] = t; qsort( collection, lo, l-1 ); qsort( collection, l+1, hi ); } }
Jedi Java
public static <T> List<T> sort(final List<T> collection, final Comparator<T> comparator) {
if (collection.size() < 2) {
return asList(collection);
}
final T head = head(collection);
final List<T> tail = tail(collection);
final List<T> lower = select(tail, lessThan(head, comparator));
final List<T> upper = select(tail, not(lessThan(head, comparator)));
return append(sort(lower, comparator), list(head), sort(upper, comparator));
}
Get All Non-Empty Strings From a Collection
Conventional Java
This example uses:
- FunctionalPrimitives.select(java.util.Collection, Filter)
- FirstOrderLogic.not(Filter).
... public List<String> getNonEmptyStrings(Collection<String> strings) { List<String> result = new ArrayList<String>(); Iterator<String> iter = strings.iterator(); while (iter.hasNext()) { String s = iter.next(); if (s.length() > 0) { result.add(s); } } return result; } ...
Options
(see Options)
Everyone has come across nasty code like this in many languages:
String foo = map.get("key"); if (foo == null) { throw new WhatsItException("Where's the foo"); } // use foo
These situations occur during lazy initialisation, retrieving values from maps, retrieving data from a database. It's everywhere and it's nasty.
The reason it's nasty is that a null reference sits around waiting for some unfortunate code to dereference it. The even more unfortunate programmer has to then figure where it came from which is not always trivial.
This is where Option comes in. Let's rewrite the above code block:
Option<String> foo = Options.get(map, "key"); foo.match(new OptionMatcher() { public void caseSome(String value) { // excellent we can use the value } public void caseNone(None<String> none) { throw new WhatsItException("Where's the foo?"); } });
The point is that there are no nulls in this code and the possibility that the value may not exist has to be dealt with.
If you just want a default value if the Option is a None then:
String foo = myOption.getOrElse("default value"); // or String foo = myOption.getOrElse(aFunctor);
where aFunctor is a Jedi Functor0 that will generate the value you need.
This is JEDI though, so there is also another way to use Options:
Option<String> foo = Options.get(map, "key"); foo.match(someCommand, noneCommand);
Where someCommand and noneCommand are Commands to be executed depending on whether foo is a Some or None. (The commands could be generated by annotations against existing methods of course.) The someCommand will be given the actual value contained in the Some instance so it does not need to match on an Option. This can be much more concise with a static import:
get(map, "key").match(someCommand, noneCommand);
Another use is performing some action if a value exists. Normally this requires a null check. In Jedi, with Commands and Option:
Option<String> foo = ...
foo.forEach(commandTakingString);
Project Euler Example
This example illustrates solutions to Project Euler problems using Jedi.
The code was compiled with the jediSuppressProxySuffix switch which is why none of the factory methods have the word 'proxy' in them - see the example build file included in the distribution's examples.
package jedi.example; import static jedi.assertion.Assert.assertEqual; import static jedi.assertion.Assert.assertTrue; import static jedi.example.ProjectEulerStaticClosureFactory.divFilter; import static jedi.example.ProjectEulerStaticClosureFactory.isPalindromeFilter; import static jedi.example.ProjectEulerStaticClosureFactory.multiplyFunctor2; import static jedi.example.ProjectEulerStaticClosureFactory.sumFunctor2; import static jedi.functional.Coercions.list; import static jedi.functional.Comparables.sort; import static jedi.functional.FirstOrderLogic.or; import static jedi.functional.FunctionalPrimitives.fold; import static jedi.functional.FunctionalPrimitives.head; import static jedi.functional.FunctionalPrimitives.produce; import static jedi.functional.FunctionalPrimitives.reverse; import static jedi.functional.FunctionalPrimitives.select; import java.util.ArrayList; import java.util.List; import jedi.annotation.JediCut; import jedi.annotation.JediFilter; import jedi.annotation.JediFunctor; public class ProjectEuler { /** * Find the sum of all the multiples of 3 or 5 below 1000. */ @SuppressWarnings("unchecked") public void problemOne() { assertEqual(new Integer(233168), fold(0, select( range(1,1000), or( divFilter(this, 3), divFilter(this, 5))), sumFunctor2(this)), "Problem one: Find the sum of all the multiples of 3 or 5 below 1000."); } /** * The sum of the even Fibonacci numbers which are at most 4,000,000 */ public void problemTwo() { assertEqual(new Integer(4613732), fold(0, select( fib(4000000), divFilter(this, 2)), sumFunctor2(this)), "Problem two: The sum of the even Fibonacci numbers which are at most 4,000,000"); } /** * what is the largest prime factor of the number 600851475143 ? */ public void problemThree() { assertTrue(true, "Problem three: Nothing interesting for JEDI to do!"); } /** * Find the largest palindrome made from the product of two 3-digit numbers. */ public void problemFour() { assertEqual(new Integer(906609), head( reverse( sort( select( produce( range(100,1000), range(100,1000), multiplyFunctor2(this)), isPalindromeFilter(this))))), "Problem four: Find the largest palindrome made from the product of two 3-digit numbers."); } /** * This method has a JediFilter which creates the isPalindromeFilter statically imported above. */ @JediFilter boolean isPalindrome(Integer x) { String s = x.toString(); return s.equals(new StringBuffer(s).reverse().toString()); } /** * This method has a JediFilter which creates the divFilter statically imported above. * @return x % y == 0 */ @JediFilter(cut= {@JediCut(parameters="y")}) boolean div(Integer x, Integer y) { return x % y == 0; } /** * This method has a JediFunctor which creates the sumFunctor2 statically imported above. * @return a + b */ @JediFunctor Integer sum(Integer a, Integer b) { return a + b; } /** * This method has a JediFunctor which creates the multiplyFunctor2 statically imported above. * @return a * b */ @JediFunctor Integer multiply(Integer a, Integer b) { return a * b; } public List<Integer> fib(int limit) { return fibh(new ArrayList<Integer>(), limit); } private List<Integer> fibh(List<Integer> c, int limit) { if (c.isEmpty()) return fibh(list(new Integer(1), new Integer(0)), limit); final int sum = c.get(0) + c.get(1); if (sum > limit) return c; c.add(0, sum); return fibh(c, limit); } public List<Integer> range(int a, int b) { List<Integer> list = new ArrayList<Integer>(b - a); for (int i = a; i < b; i++) { list.add(i); } return list; } public static void main(String[] args) { ProjectEuler projectEuler = new ProjectEuler(); projectEuler.problemOne(); projectEuler.problemTwo(); projectEuler.problemThree(); projectEuler.problemFour(); } }


