Rick

Rick
Rick

Wednesday, June 13, 2012

I wrote a BNF DSL with Java vargs that can also parse text (works for mostly simple things now), if you have seen the query DSL I wrote for DAO is is somewhat similar in concept. You define the rules which are stateless, they create a context and parse the text. My eventual goal is to use the BNF DSL metadata to code generate a parser. The idea being you can define a parser on the fly using the BNF DSL, but this type of reuse has overhead so you can also use the rules, feed it into the new template engine I wrote, and generate a much faster parser if performance is critical. Then you just use the code generated parser instead of the on the fly BNF DSL parser. So the BNF DSL can parse text or work as the seed syntax tree to generate a fast parser. I have no idea why I am doing this. Other than it was really fun. It is all text based now, but I can see working on a BNF DSL for binary data for things like protocols and such. One reason I am doing this for sure is the dreaded one off. I am so sick of writing parser by hand and being one off or having some weird edge case.

I started this because I wrote a template language based on Python's template language, but in Java as part of my effort to make Java more fluent like Python. I added a loop, because every time I use on of these template, I was always think, why does it not have a simple loop concept. Well once I had the loop, it seems like I need an *if* concept, then of course I need an expression language. I started to hack the expression language together and was like damnit this the 20th time I have done this... wouldn't it be nice to have a BNF DSL and I can declare my syntax and get a starting parser.... blah blah blah... SQUIRREL!

Earlier this year, I wrote my own JSON parser in Java. I wanted something small, fast and light that did not have 50,000 bells and whistles and one I could hack with. Also earlier this year, I forked a websocket project and added protocol negotiation to it (an optional feature), mainly to better understand websockets.

Sunday, June 10, 2012

Got basic iteration added to Java template engine. Java code (note you can use format and lines instead of fmt and lns).
  String st = fmt(
    lns("This is a test of my sanity",
     "This is a test of my sanity",
     "{@loop:test.emps} ",
     "This is the body of the loop",
     "firstName = {iter.firstName}",
     "{@endloop}",
     "This text is outside of the loop"
      )
    ,
    mp("test",
      mp("emps",
        ls(emp("Rick", "Hightower", 1000.0),
          emp("Bob", "Hightower", 7000.0)))));
  print("fmt18", st);

Output:
fmt18 This is a test of my sanity
This is a test of my sanity
 
This is the body of the loop
firstName = Rick
 
This is the body of the loop
firstName = Bob
This text is outside of the loop

I also got formatting working last night. I think I am done for a while. I had my fun.

Implemented Python style formatting in Java

This is pretty early, and well... probably full of bugs... It is just a proof of concept at this point, but seems to work.

Python style template/formatting in Java

  // >>> '{0}, {1}, {2}'.format('a', 'b', 'c')
  // 'a, b, c'
  String str = format("{0}, {1}, {2}", "a", "b", "c");
  print("fmt1", str);
  //fmt is the short form of format
  str = fmt("{0}, {1}, {2}", "a", "b", "c");
  print("fmt2", str);
  // >>> '{}, {}, {}'.format('a', 'b', 'c') # 2.7+ only
  // 'a, b, c'
  str = fmt("{}, {}, {}", "a", "b", "c");
  print("fmt3", str);

  // >>> '{2}, {1}, {0}'.format('a', 'b', 'c')
  // 'c, b, a'
  str = fmt("{2}, {1}, {0}", "a", "b", "c");
  print("fmt4", str);

  // >>> '{2}, {1}, {0}'.format(*'abc') # unpacking argument sequence
  // 'c, b, a'
  str = fmt("{2}, {1}, {0}", array("abc"));
  print("fmt5", str);

  str = fmt("{2}, {1}, {0}", (Object[]) array(1, 2, 3));
  print("fmt6", str);

  str = fmt("{2}, {1}, {0}", oarray(1, 2, 3));
  print("fmt7", str);

  str = fmt("{2}, {1}, {0}", oar(1, 2, 3));
  print("fmt8", str);

  // >>> '{0}{1}{0}'.format('abra', 'cad') # arguments' indices can be
  // repeated
  // 'abracadabra'
  str = fmt("{0}{1}{0}", "abra", "cad");
  print("fmt9", str);
  // >>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N',
  // longitude='-115.81W')
  // 'Coordinates: 37.24N, -115.81W'
  str = fmt("Coordinates: {latitude}, {longitude}",
    mp("latitude", "37.24N", "longitude", "-115.81W"));
  print("fmt10", str);
  // >>> "{1:0>+10.3f},{1}".format(2.2,3.0)
  // '0000+3.000,3.0'
  str = fmt("{1:2.2f},{1}", 2.2, 3.0);
  print("fmt11", str);

  str = fmt("Coordinates: {latitude:2.2f}, {longitude}",
    mp("latitude", 37.24, "longitude", -115.81));
  print("fmt12", str);

  str = fmt("{1[0]:2.2f},{1}", 2.2, ls(2.2, 3.0));
  print("fmt13", str);

  str = fmt("0={0},1={1},1.my2={1.my2:2.2f}", 2.2,
    mp("my", 2.2, "my2", 3.0));
  print("fmt14", str);

  str = fmt("{0}, fn={0.firstName}, salary={0.salary:2.2f}",
    emp("Rick", "Hightower", 1000.0));
  print("fmt15", str);

  str = fmt(
    "{0}, fn={emps[0].firstName}, salary={emps[0].salary:2.2f}",
    mp("emps",
      ls(emp("Rick", "Hightower", 1000.0),
        emp("Bob", "Hightower", 7000.0))));
  print("fmt16", str);

  print();
  print();
  str = fmt(
    "a={test}\n" + "b={test.emps}\n" + "c={test.emps[0]}\n"
      + "d={test.emps[0].firstName}\n"
      + "e={test.emps[0].salary:2.2f}",
    mp("test",
      mp("emps",
        ls(emp("Rick", "Hightower", 1000.0),
          emp("Bob", "Hightower", 7000.0)))));
  print("fmt17", str);

...
 static Employee emp(String firstName, String lastName, double salary) {
  return new Employee(firstName, lastName, salary);
 }

 public static class Employee {
  String firstName;
  String lastName;

  public String getFirstName() {
   return firstName;
  }

  public String getLastName() {
   return lastName;
  }

  public void setSalary(double salary) {
   this.salary = salary;
  }

  double salary;

  public Employee(String firstName, String lastName, double salary) {
   super();
   this.firstName = firstName;
   this.lastName = lastName;
   this.salary = salary;
  }

  @Override
  public String toString() {
   return "Employee [firstName=" + firstName + ", lastName="
     + lastName + ", salary=" + salary + "]";
  }

 }

Output

fmt1 a, b, c 
fmt2 a, b, c 
fmt3 a, b, c 
fmt4 c, b, a 
fmt5 c, b, a 
fmt6 3, 2, 1 
fmt7 3, 2, 1 
fmt8 3, 2, 1 
fmt9 abracadabra 
fmt10 Coordinates: 37.24N, -115.81W 
fmt11 3.00,3.0 
fmt12 Coordinates: 37.24, -115.81 
fmt13 2.20,[2.2, 3.0] 
fmt14 0=2.2,1={my2=3.0, my=2.2},1.my2=3.00 
fmt15 Employee [firstName=Rick, lastName=Hightower, salary=1000.0], fn=Rick, salary=1000.00 
fmt16 null, fn=Rick, salary=1000.00 
fmt17 a={emps=[Employee [firstName=Rick, lastName=Hightower, salary=1000.0], Employee [firstName=Bob, lastName=Hightower, salary=7000.0]]}
b=[Employee [firstName=Rick, lastName=Hightower, salary=1000.0], Employee [firstName=Bob, lastName=Hightower, salary=7000.0]]
c=Employee [firstName=Rick, lastName=Hightower, salary=1000.0]
d=Rick
e=1000.00 

Implementation

 public static String mfmt(String str, Map<?, ?> map) {
  return mapFormat(str, map);
 }
 public static String mapFormat(String str, Map<?, ?> map) {

  StringBuilder builder = new StringBuilder(str.length());
  StringBuilder contents = new StringBuilder(32);
  StringBuilder formatRulesContents = new StringBuilder(32);

  
  char[] charArray = str.toCharArray();
  for (int index=0; index<charArray.length; index++) {
   char c = charArray[index];
   if (c=='{') {
    contents.setLength(0);
    formatRulesContents.setLength(0);
    index++;
    boolean formatRules=false;
    
    for (;index<charArray.length && c!='}'; index++) {
     c = charArray[index];
     if (c=='[' ||  c=='!' || c==':' || c=='.') {
      formatRules=true;
     }
     if (c!='}') {
      if (!formatRules) {
       contents.append(c);
      } else {
       formatRulesContents.append(c);
      }
     }
    }
     if (!formatRules) {
         builder.append(map.get(contents.toString()));
     } else {
      builder.append(formatRule(map.get(contents.toString()), formatRulesContents.toString()));
    }

    index--;
   } else {
    builder.append(c);
   }
  }
  return builder.toString();
 }

 public static String fmt(String str, Object... args) {
  return format(str, args);
 }
 public static String format(String str, Object... args) {
  
  if (args.length==1) {
   if (args[0] instanceof char[]) {
    return cformat(str, (char[]) args[0]);
   } else if (args[0] instanceof Map) {
    return mapFormat(str, (Map<?,?>)args[0]);
   } else {
    return arrayFormat(str, args);
   }
  } else {
   return arrayFormat(str, args);
  }
 }

 public static String arfmt(String str, Object... args) {
  return format(str, args);
 }
 public static String arrayFormat(String str, Object... args) {

  StringBuilder builder = new StringBuilder(str.length());
  StringBuilder contents = new StringBuilder(32);
  StringBuilder formatRulesContents = new StringBuilder(32);
  
  int argIndexKeeper = 0;
  int argIndex=-666;
  
  char[] charArray = str.toCharArray();
  for (int index=0; index<charArray.length; index++) {
   char c = charArray[index];
   if (c=='{') {
    contents.setLength(0);
    formatRulesContents.setLength(0);
    index++;
    boolean formatRules=false;
    
    for (;index<charArray.length && c!='}'; index++) {
     c = charArray[index];
     if (c=='[' ||  c=='!' || c==':' || c=='.') {
      formatRules=true;
     }
     if (c!='}') {
      if (!formatRules) {
       contents.append(c);
      } else {
       formatRulesContents.append(c);
      }
     }
    }
    
    String sindex = contents.toString().trim();
    if (sindex.isEmpty()) {
     argIndex = argIndexKeeper;
     if (!formatRules) {
      builder.append(args[argIndex].toString());
     } else {
      builder.append(formatRule(args[argIndex], formatRulesContents.toString()));
     }
     argIndexKeeper++;
    } else {
      argIndex = Integer.parseInt(sindex);
      if (!formatRules) {
       builder.append(args[argIndex].toString());
      } else {
       builder.append(formatRule(args[argIndex], formatRulesContents.toString()));
     }
    }
    index--;
   } else {
    builder.append(c);
   }
  }
  return builder.toString();
 }

 
 private static String formatRule(Object object, String rule) {
  StringBuilder format = new StringBuilder(16);
  StringBuilder idx = new StringBuilder(16);
  List <Object> idxs  = new ArrayList<Object>(16);
  char[] charArray = rule.toCharArray();
  
  boolean hasFormat = false;
  boolean hasIndex = false;
  boolean hasDotIndex = false;
  
  for (int index=0; index< charArray.length; index++) {
   char c = charArray[index];
   
   
   if(hasFormat) {
    format.append(c);
   } else if (hasIndex) {
    if (c == ']') {
     idxs.add(Integer.parseInt(idx.toString()));
     hasIndex = false;
    } else {
     idx.append(c);
    }
   } else if (hasDotIndex) {
    if (c=='['  || c == '.' || c == ':') {
     idxs.add(idx.toString());
     hasDotIndex = false;
    } else {
     idx.append(c);
     if  (index+1 == charArray.length) {
      idxs.add(idx.toString());
      hasDotIndex = false;      
     }
    }
   }

   if (c == ':') {
    hasFormat = true;
    format.setLength(0);
   } else if (c == '[') {
    hasIndex = true;
    idx.setLength(0);   
   } else if (c == '.') {
    hasDotIndex = true;
    idx.setLength(0);   
   }

  }
  if (hasFormat) {
   format.insert(0, '%');
  }
  
  for (Object oindex : idxs) {
   if (oindex instanceof Integer) {
    int index = (Integer)oindex;
    if (object.getClass().isArray()) {
     object = Array.get(object, index);
    } else if (object instanceof List) {
     object = index(((List<?>)object), index);
    } else {
     object = null;
    }
   } else {
    String key = (String)oindex;
    if (object instanceof Map) {
     @SuppressWarnings("unchecked")
     Map <String,?> map = (Map<String, ?>) object;
     object = map.get(key);
    } else {
     object.getClass().getDeclaredMethods();
     Class<? extends Object> clz = object.getClass();
     outer:
     while (clz!=Object.class) {
      Method[] methods = clz.getDeclaredMethods();
      for (Method method : methods) {
       method.setAccessible(true);
       if (method.getParameterTypes().length==0 && method.getName().toLowerCase().endsWith(key.toLowerCase())
         && (method.getName().startsWith("is") || method.getName().startsWith("get") || 
           method.getName().length()==key.length())
         ) {
        try {
         object = method.invoke(object, (Object[])null);
         break outer;
        } catch (Exception ex) {
         continue;
        }
       }
      }
      Field[] declaredFields = clz.getDeclaredFields();
      for (Field field : declaredFields) {
       field.setAccessible(true);
       if (field.getName().equals(key)) {
        try {
         object = field.get(object);
         break outer;
        } catch (Exception ex) {
         break;
        }
       }
      }
      
      clz = clz.getSuperclass();
     }
    }
   }
  }
  if (object==null) {
   return "";
  } else if (hasFormat) {
   return String.format(format.toString(), object);
  } else {
   return object.toString();
  }
  
 }

 public static String cfmt(String str, char... args) {
  return cformat(str, args);
 }
 public static String cformat(String str, char... args) {
  StringBuilder builder = new StringBuilder(str.length());
  StringBuilder contents = new StringBuilder(32);
  
  int argIndexKeeper = 0;
  int argIndex=-666;
  
  char[] charArray = str.toCharArray();
  for (int index=0; index<charArray.length; index++) {
   char c = charArray[index];
   if (c=='{') {
    contents.setLength(0);
    index++;
    
    for (;index<charArray.length && c!='}'; index++) {
     c = charArray[index];
     if (c!='}') {
      contents.append(c);
     }
    }
    
    String sindex = contents.toString().trim();
    if (sindex.isEmpty()) {
     argIndex = argIndexKeeper;
     builder.append(args[argIndex]);
     argIndexKeeper++;
    } else {
      argIndex = Integer.parseInt(sindex);
      builder.append(args[argIndex]);
    }
    index--;
   } else {
    builder.append(c);
   }
  }
  return builder.toString();
 }

Saturday, June 9, 2012

More fooling around with EasyJava

I implemented all of the basic map, reduce, etc. from Python in Java. Now I went through the Python string tutorial, and Python list tutorial. I implemented slice, slice replacement, etc. in Java. I am learning all sorts of things about Java Generics in the process.

Python versus EasyJava:Multiline strings


  print """
  Usage: thingy [OPTIONS]
       -h                        Display this usage message
       -H hostname               Hostname to connect to
  """

  print (lines(
"    Usage: thingy [OPTIONS]",
"        -h                        Display this usage message",
"        -H hostname               Hostname to connect to"
    ));

Ok... that is the best I could come up with. It is not the same at all, but it might be marginally easier than having to concatenate strings.

Python versus EasyJava : Adding strings

  >>> word = 'Help' + 'A'
  >>> print (word)
  
  String word;
  word = "Help" + "A";
  print (word);
Ok. There was not much to do here. Java does this right already. :)

Python versus EasyJava : String slicing

  print (word[4])
  print (word[0:2])
  print (word[2:4])

Output:
  'A'
  'He'
  'lp'  
  print(slice(word,4));
  print(slice(word,0,2));
  print(slice(word,2,4));
I also implemented slice for lists, and added a few more collection methods. I implemented a replacement slice too.

All of the rest

//  >>> 'x' + word[1:]
//  'xelpA'
//  >>> 'Splat' + word[4]
//  'SplatA'  
  print(lines (
   "x" + slice(word,1),
   "Splat" + word.charAt(4)
  ));
  
//  >>> word[:2] + word[2:]
//  'HelpA'
//  >>> word[:3] + word[3:]
//  'HelpA'  
  print(lines (
    slice(word,0,2) + slice(word,2),
    slice(word,0,3) + slice(word,3)
   ));
//  >>> word[1:100]
//  'elpA'
//  >>> word[10:]
//  ''
//  >>> word[2:1]
//  ''  
  print(lines (
    "1,00 " + slice(word,1,100),
    "10 " + slice(word,10),
    "2,1 " +  slice(word,2,1)
   ));

//  >>> word[-1]     # The last character
//  'A'
//  >>> word[-2]     # The last-but-one character
//  'p'
//  >>> word[-2:]    # The last two characters
//  'pA'
//  >>> word[:-2]    # Everything except the last two characters
//  'Hel'
  //slice has a alias called slc,  slc=slice, index=idx
  print(lines (
    "-1   :" + slc(word,-1),
    "-2   :" + idx(word, -2),
    "-2   :" + slc(word,-2),
    "0,-2 :" + slc(word,0,-2)
   ));
//  >>> word[-100:]
//  'HelpA'  
  print (slice(word,-100));

  List<? extends Object> a;
//  a = ['spam', 'eggs', 100, 1234]
//  print (a)
//  ['spam', 'eggs', 100, 1234]
  a = ls("spam", "eggs", 100, 1234);
  print (a);
//ls and list do the same thing
  a = list("spam", "eggs", 100, 1234);
  print (a);

 //>>> a[0]
 //'spam'
 print (idx(a,0)); 
 //>>> a[3]
 //1234
 print (idx(a,3));  
 //>>> a[-2]
 //100
 print (idx(a,3)); 
 //>>> a[1:-1]
 //['eggs', 100]
 print (slc(a,1,-1));  
 //>>> a[:2]
 print (slc(a,0,2));  
 //>>> a[:2] + ['bacon', 2*2]
 //['spam', 'eggs', 'bacon', 4]
 print ("addls",
   ls(slc(a,0,2), ls ("bacon", 2*2))
 );

// >>> 3*a[:3] + ['Boo!']
// ['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!'] 
 
 
 print ( ls ( mul( 3, slc( a,0,3 ) ), ls( "Boo!" ) ) );
 //ls(mul(3,slc(a,0,3)),ls("Boo!"))
 //3*a[:3]+['Boo!']
 //3*a[:3]+['Boo!']3*a[:3]+['Boo!'] //java is twice as long
 
//  a[:]
// ['spam', 'eggs', 100, 1234] 
 print (copy (a) );
 
// >>> a
// ['spam', 'eggs', 100, 1234]
// >>> a[2] = a[2] + 23
// >>> a
// ['spam', 'eggs', 123, 1234] 
 
 //Java is strongly typed so the above is a bit harder, better with uniform types.
 List<Integer> b = ls (1,2,100,1234);
 b.set(2, b.get(2) + 23);
 print (b);
 
 //Java is strongly typed so the above is a bit harder 
 ((List<Integer>)a).set(2, ((Integer)a.get(2) + 23));
 print (a);
 
 List<Integer> ia = (List<Integer>)a;
 List<String> sa = (List<String>)a;
 List<Object> oa = (List<Object>)a;
 
 //b.set(2,b.get(2)+23);
 //a[2]=a[2]+23         //for uniform type, python is 1/2 size
 //((List<Integer>)a).set(2,((Integer)a.get(2)+23)); //for non-uniform type, python is about 1/5 the size
 
// >>> # Replace some items:
//  ... a[0:2] = [1, 12]
//  >>> a
// [1, 12, 123, 1234]
 List<Integer> ia2 = copy(ia);
 
 replace(ia2, 0, 2, ls(1,12));
 print ("ia2", ia2);
 
 rpl(ia,0,2,ls(1,12));
 print ("ia", ia);

Now the implementation....
package com.easyjava;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Date;

public class EasyJava {
 private static final Logger log = Logger.getLogger(EasyJava.class.getName());
 private static final Logger appLog = Logger.getLogger(sprop(pkey(EasyJava.class,"appLog"), "genericLog"));

 public static final Class<String> string = String.class;
 public static final Class<Integer> integer = Integer.class;
 public static final Class<Float> flt = Float.class;
 public static final Class<Double> dbl = Double.class;
 public static final Class<Date> date = Date.class;
 public static final boolean debug;
 
 static {
  debug = sbprop(pkey(EasyJava.class, "debug"));
 }
 

 // HELPER
 // HELPER

 // HELPER
 // HELPER
 private static Class<?> clazz(Object that) {
  if (that instanceof Class) {
   return (Class<?>) that;
  } else {
   return that.getClass();
  }
 }
 
 public static String mykey(Class<?> cls, final String key) {
  return pkey(EasyJava.class, key);
 }

 public static String pkey(Class<?> cls, String key) {
  return cls.getName() + "." + key;
 }

 public static String sprop(String key) {
  return System.getProperty(key);
 }

 public static String sprop(String key, String defaultValue) {
  return System.getProperty(key, defaultValue);
 }

 public static boolean sbprop(String key) {
  return Boolean.getBoolean(key);
 }


 public static void print (Object... items) {
  StringBuilder builder = new StringBuilder(256);
  for (Object item : items) {
   builder.append(item);
   builder.append(' ');
  }
  System.out.println(builder);
 }
 
 public static void printf (String fmt, Object... args) {
  System.out.printf(fmt, args);
 }
 public static String sprintf (String fmt, Object... args) {
  return String.format(fmt, args);
 }
 public static void fprintf (Logger log, String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  log.info(String.format(fmt, args));
 }

 //Logging
 //Logging
 //Logging
 public static void info (Logger log, String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  log.info(String.format(fmt, args));
 }
 public static void debug (Logger log, String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  log.fine(String.format(fmt, args));
 }
 public static void trace (Logger log, String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  log.finest(String.format(fmt, args));
 }
 public static void info (String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  appLog.info(String.format(fmt, args));
 }
 public static void fprintf (String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  appLog.info(String.format(fmt, args));
 }
 public static void debug (String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  appLog.fine(String.format(fmt, args));
 }
 public static void trace (String fmt, Object... args) {
  if (debug) { printf(fmt, args); return;}
  appLog.finest(String.format(fmt, args));
 }

 
 @SuppressWarnings("serial")
 public static class AssertionException extends RuntimeException {

  public AssertionException() {
   super();
  }

  public AssertionException(String message, Throwable cause) {
   super(message, cause);
  }

  public AssertionException(String message) {
   super(message);
  }

  public AssertionException(Throwable cause) {
   super(cause);
  }  
 }
 
 @SuppressWarnings("serial")
 public static class ReflectionException extends RuntimeException {

  public ReflectionException() {
   super();
  }

  public ReflectionException(String message, Throwable cause) {
   super(message, cause);
  }

  public ReflectionException(String message) {
   super(message);
  }

  public ReflectionException(Throwable cause) {
   super(cause);
  }  
 }

 public static void die(boolean condition, String message) {
  if (condition) {
   throw new AssertionException(message);
  }
 }
 public static void die(String message) {
  throw new AssertionException(message);
 }
 
 public static void die(String message, Object... args) {
  throw new AssertionException(String.format(message, args));
 }
 
 
 
 // CREATIONAL
 // CREATIONAL
 
 // CREATIONAL
 // CREATIONAL 
 public static interface Entry<K,V> {
  K key();
  V value();
 }

 private static class EntryImpl<K, V> implements Entry<K, V>{
  EntryImpl(K k, V v) {this.k=k; this.v=v;}
  K k;
  V v;
  @Override
  public K key() {
   return k;
  }
  @Override
  public V value() {
   return v;
  }
 }

 public static <K, V> Entry<K, V> kv (final K k, final V v) {
  return new EntryImpl<K,V>(k, v);
 }
 
 public static <K, V> Entry <K, V> entry (final K k, final V v) {
  return new EntryImpl<K,V>(k,v);
 }
 
 public static <V> List<V> ls(final V... array) {
  return list(array);
 }
 
 public static <V> List<V> list(final V... array) {
  ArrayList<V> list = new ArrayList<V>(array.length);
  for (V o : array) {
   list.add(o);
  }
  return list;
 }

 public static <V> List<V> ls(final Collection<V> col) {
  return list(col);
 }

 public static <V> List<V> list(final Collection<V> col) {
  return new ArrayList<V>(col);
 }

 public static <V> List<V> ls(Collection<V> lst, final Collection<?>... others) {
  return list(lst, others);
 }
 
 @SuppressWarnings("unchecked")
 public static <V> List<V> list(Collection<V> lst, final Collection<?>... others) {
  int total=lst.size();
  for (Collection<?> c : others) {
   total += c.size();
  }
  ArrayList<Object> list = new ArrayList<Object>(total);
  list.addAll(lst);
  for (Collection<?> c : others) {
   list.addAll(c);
  }
  return (List<V>) list;  
 }
 
 public static <V> List<V> copy(final List<V> col) {
  return new ArrayList<V>(col);
 }
 public static <V> Set<V> copy(final Set<V> col) {
  return new HashSet<V>(col);
 }
 public static <V> SortedSet<V> copy(final SortedSet<V> col) {
  return new TreeSet<V>(col);
 }
 public static String copy(final String str) {
  return new String(str);
 }
 public static StringBuilder copy(final StringBuilder str) {
  return new StringBuilder(str);
 }
 public static CharSequence copy(final CharSequence str) {
  return str.toString();
 }


 public static <V> List<V> mul(int x, Collection<V> lst) {
  ArrayList<V> list = new ArrayList<V>(x * lst.size());
  for (int index=0; index < x; index++) {
   for (V element : lst){
    list.add(element);
   }
  }
  return list;
 }
 public static String mul(int x, CharSequence seq) {
  StringBuilder builder = new StringBuilder(x * seq.length());
  for (int index=0; index < x; index++) {
   builder.append(seq);
  }
  return builder.toString();
 }
 
 
 public static <V> Set<V> set(final V... array) {
  return new HashSet<V>(list(array));
 }
 
 public static List<Integer> range(int stop) {
  return range(0, stop);
 }

 public static List<Integer> range(int start, int stop) {
  ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
  for (int index=start; index<stop; index++) {
   range.add(index);
  }
  return range;
 }

 public static List<Integer> range(int start, int stop, int inc) {
  ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
  for (int index=start; index<stop; index+=inc) {
   range.add(index);
  }
  return range;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  return map;
 }
 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  return map;
 }
 
 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  return map;
 }
 
 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  map.put(k6, v6);
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  map.put(k6, v6);
  map.put(k7, v7);
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  map.put(k6, v6);
  map.put(k7, v7);
  map.put(k8, v8);  
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8,
   K k9, V v9) {
  HashMap<K, V> map = new HashMap<K, V>(10);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  map.put(k6, v6);
  map.put(k7, v7);
  map.put(k8, v8);
  map.put(k9, v9);  
  return map;
 }

 public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8,
   K k9, V v9, Entry<K,V>...entries) {
  HashMap<K, V> map = new HashMap<K, V>(10 + entries.length);
  map.put(k0, v0);
  map.put(k1, v1);
  map.put(k2, v2);
  map.put(k3, v3);
  map.put(k4, v4);
  map.put(k5, v5);
  map.put(k6, v6);
  map.put(k7, v7);
  map.put(k8, v8);
  map.put(k9, v9);  
  for (Entry<K,V> entry: entries) {
   map.put(entry.key(), entry.value());
  }
  return map;
 }
 
 public static <K, V> Map<K, V> mp(Collection<K> keys, Collection<V> values) {
  HashMap<K, V> map = new HashMap<K, V>(10 + keys.size());
  Iterator<V> iterator = values.iterator();
  for (K k : keys) {
   if (iterator.hasNext()) {
    V v = iterator.next();
    map.put(k, v);
   } else {
    map.put(k,  null);
   }
  }
  return map;
 }

 public static <K, V> Map<K, V> mp(K[] keys, V[] values) {
  HashMap<K, V> map = new HashMap<K, V>(10 + keys.length);
  int index = 0;
  for (K k : keys) {
   if (index < keys.length ) {
    V v = values[index];
    map.put(k, v);
   } else {
    map.put(k,  null);
   }
   index++;
  }
  return map;
 }

 public static <K, V> Map<K, V> dict(Entry<K,V>...entries) {
  HashMap<K, V> map = new HashMap<K, V>(5);
  for (Entry<K,V> entry: entries) {
   map.put(entry.key(), entry.value());
  }
  return map;
 }
 
 //
 // Functional 
 //
 

 //
 // Functional 
 //
 public static interface Function <T> {
  T execute(Object... params);
 }
 
 private static class FunctionImpl<T> implements Function<T> {
  Method method;
  Object that;

  FunctionImpl(Class<T> clazz, Method method, Object that) {
   this.method=method; 
   this.that = that;
  }
  
    
  @SuppressWarnings("unchecked")
  public T execute(Object... params) {
   
   T ret = null;
   try {
    ret = (T) method.invoke(that, params);
   } catch (Exception ex) {
    throw new ReflectionException("unable to execute function " + method.getName(), ex);
   }
   return ret;
  }
  
 }


 public static <T> Function<T> f(Class<T> returnType, Object that, Object... args) {
  try {
   return fn(returnType, that, "f", args);
  } catch (Exception e) {
   throw new ReflectionException(e);
  }
 }

 public static Function<?> f(Object that, Object... args) {
  try {
   return fn(that, "f", args);
  } catch (Exception e) {
   throw new ReflectionException(e);
  }
 }

 public static Function<?> fn(Object that, Object name, Object... args) {
  return fn(Object.class, that, name, args);
 }
 
 public static <T> Function<T> fn(Class<T> returnType, Object that, Object name, Object... args) {
  try {
   Method[] methods = clazz(that).getDeclaredMethods();
   for (Method m : methods) {
    if (args.length <= m.getParameterTypes().length) {
     if (m.getName().equals(name.toString())) {
      m.setAccessible(true);
      if (Modifier.isStatic(m.getModifiers())) {
       return new FunctionImpl<T>(returnType, m, null);
      } else {
       return new FunctionImpl<T>(returnType, m, that);
      }
     }
    }
   }
  } catch (Exception ex) {
   log.log(Level.SEVERE, String.format("Unable to find function that=%s, name=%s, args=%s", that, name, list(args)), ex);
  }
  die("Unable to find function that=%s, name=%s, args=%s", that, name, list(args));
  return null;
 }

 public static void enumerate(Function<?> f, Collection<?> c) {
  int index = 0;
  for (Object o : c) {
   f.execute(index, o);
   index++;
  }
 }
 
 public static Collection<?> filter(Function<?> f, List<?> l) {
  return gfilter(f,l);
 }

 public static Collection<?> filter(Function<?> f, Collection<?> c) {
  return gfilter(f, c);
 }
 
 public static <T> Collection<T> gfilter(Function<?> f, List<T> l) {
  ListIterator<?> listIterator = l.listIterator();
  while (listIterator.hasNext()) {
   Boolean b = (Boolean) f.execute(listIterator.next());
   if (!b) {
    listIterator.remove();
   }
  }
  return l;
 }

 public static <T> Collection<T> gfilter(Function<?> f, Collection<T> in) {
  ArrayList<Object> removeList = new ArrayList<Object>(in.size());
  ArrayList<T> c = new ArrayList<T>(in);

  for (Object o : in) {
   Boolean b = (Boolean) f.execute(0);
   if (!b) {
    removeList.add(o);
   }   
  }
  for (Object o: removeList) {
   c.remove(o);
  }
  return c;
 }

 public static List<?> map(Function<?> f, List<?>...cols) {
  return gmap(f, cols);
 }
 
 public static <OUT> List<OUT> gmap(Function<OUT> f, List<?>...cols) {
  
  int max = Integer.MIN_VALUE;
  
  for (int index=0; index < cols.length; index++) {
   Collection<?> c = cols[index];
   if (c.size() > max) {
    max =c.size();
   }
  }
  
  ArrayList<OUT> mapList = new ArrayList<OUT>(max);  
  for (int row = 0; row < max; row++) {
   ArrayList<Object> args = new ArrayList<Object>(cols.length);

   for (int index=0; index < cols.length; index++) {
    List<?> c = cols[index];
    if (row < c.size()) {
     args.add(c.get(row));
    } else {
     args.add(null);
    }
   }
   OUT object = f.execute(args.toArray(new Object[cols.length]));
   mapList.add(object);

  }

  return mapList;
 }

 public static List<?> map(Function<?> f, Collection<?> c) {
  return gmap(f, c);
 }

 public static <IN, OUT> List<OUT> gmap(Function<OUT> f, Collection<IN> c) {
  ArrayList<OUT> mapList = new ArrayList<OUT>(c.size());
  for (Object o : c) {
   mapList.add(f.execute(o));
  }
  return mapList;
 }

 @SuppressWarnings("rawtypes")
 public static Object reduce(Function f, Collection<?> c) {
  return greduce(f, c);
 }
 
 @SuppressWarnings("rawtypes")
 public static Object reduce(Function f, Object [] array) {
  return greduce(f, list(array));
 }

 
 @SuppressWarnings("unchecked")
 public static <T> T greduce(Function<?> f, Collection<T> c) {
  T accumulo = null;
  int index=0;
  for (T o : c) {
   if (index==0) {
    accumulo = o;
   } else {
    accumulo = (T) f.execute(accumulo, o);
   }
   index++;
  }
  return accumulo;
 }
 

 //File
 //File
 public static interface File {
  String read(String path);
  String [] readLines(String path); 
 }
 
 //String
 //String

 public static String lns(String... lines) {
  return lines(lines);
 }
 public static String lines(String... lines) {
  return join("\n", (Object[]) lines);
 }
 
 public static String join (String delim, Object ... args) {
  StringBuilder builder = new StringBuilder (256);
  for (Object arg : args) {
   builder.append(arg.toString());
   builder.append(delim);
  }
  return builder.toString();
 }

 public static String join (char delim, Object ... args) {
  StringBuilder builder = new StringBuilder (256);
  for (Object arg : args) {
   builder.append(arg.toString());
   builder.append(delim);
  }
  return builder.toString();
 }

 public static String join (Object ... args) {
  StringBuilder builder = new StringBuilder (256);
  for (Object arg : args) {
   builder.append(arg.toString());
  }
  return builder.toString();
 }
 
 public static String slc (CharSequence str, int start, int end) {
  return slice(str, start, end);
 }
 
 public static String slice (CharSequence str, int start, int end) {
  final int length = str.length();

  //Adjust
  if (start < 0) {
   start = length + start;
  }
  if (end < 0) {
   end = length + end;
  }
    
  //Bound check
  if (start < 0) {
   start = 0;
  }
  if (start > length) {
   start = length;
  }
  if (end > str.length()) {
   end = str.length();
  }
  if (end < 0) {
   end = 0;
  }
  
  //Bound check
  if (start > end) {
   return "";
  }
  
  return str.subSequence(start, end).toString();
 }

 public static String slc (CharSequence str, int start) {
  return slice(str, start);
 }
 public static String slice (CharSequence str, int start) {
  return slice (str, start, str.length());
 }

 public static char index (CharSequence str, int index) {
  return idx(str, index);
 }
 public static char idx (CharSequence str, int index) {
  final int length = str.length();

  //Adjust
  if (index < 0) {
   index = length + index;
  }
  
  
  //Bound check
  if (index < 0) {
   index = 0;
  }
  if (index > length) {
   index = length;
  }
  
  return str.charAt(index);

 }


 public static <T> List <T> slc (List <T> lst, int start, int end) {
  return slice(lst, start, end);
 }
 public static <T> List <T> slice (List <T> lst, int start, int end) {
  final int length = lst.size();
  //Adjust
  if (start < 0) {
   start = length + start;
  }
  if (end < 0) {
   end = length + end;
  }
    
  //Bound check
  if (start < 0) {
   start = 0;
  }
  if (start > length) {
   start = length;
  }
  if (end > length) {
   end = length;
  }
  if (end < 0) {
   end = 0;
  }
  
  //Bound check
  if (start > end) {
   return lst.subList(0, 0);
  }
  return lst.subList(start, end);
 }

 public static <T> void rpl (List <T> lst, int start, int end, List<T> replacement) {
  replace(lst, start, end, replacement);
 }
 public static <T> void rpl (List <T> lst, int start, List<T> replacement) {
   rpl(lst, start, replacement);
 }
 public static <T> void replace (List <T> lst, int start, List<T> replacement) {
   replace(lst, start, lst.size(), replacement);
 }
 public static <T> void replace (List <T> lst, int start, int end, List<T> replacement) {
  final int length = lst.size();
  //Adjust
  if (start < 0) {
   start = length + start;
  }
  if (end < 0) {
   end = length + end;
  }
    
  //Bound check
  if (start < 0) {
   start = 0;
  }
  if (start > length) {
   start = length;
  }
  if (end > length) {
   end = length;
  }
  if (end < 0) {
   end = 0;
  }
  
  if (start==end) {
   List<T> copy = copy(replacement);
   Collections.reverse(copy);
   for (T t: copy) {
    lst.add(start, t);
   }
   return;
  }

  
  int slicesize = end - start;
  int current = start;
  for (int index = 0; index < replacement.size(); index++, current++) {
   T t = replacement.get(index);
   if (index < slicesize ) {
    lst.set(current, t);
   } else {
    lst.add(current, t);
   }
  }
  int stop = current;
  while (current<end) {
   lst.remove(stop);
   current++;
  }
  
 }

 public static <T> List <T> slc (List <T> lst, int start) {
  return slice(lst, start);
 }
 public static <T> List <T> slice (List <T> lst, int start) {
  return slice(lst, start, lst.size());
 }
 public static <T> T idx (List<T> lst, int index) {
  return index(lst, index);
 } 
 public static <T> T index (List<T> lst, int index) {
  final int length = lst.size();

  //Adjust
  if (index < 0) {
   index = length + index;
  }
  
  
  //Bound check
  if (index < 0) {
   index = 0;
  }
  if (index > length) {
   index = length;
  }
  
  return lst.get(index);

 }
 public static <T> void  expect (T ex, T v) {
  if (ex == null && v == null) {
   return;
  }
  
  if (ex == null && v != null) {
   throw new AssertionException(sprintf("expected was null, but value was %s", v));
  }
  
  if (!ex.equals(v))  {
   throw new AssertionException(sprintf("expected was %s, but value was %s", ex, v));
  }

 }

}

Thursday, June 7, 2012

Added some more generics support to functional programming parts

Added improved Generics support so it can be more verbose, but it is better. Also improved organization and class hierarchy. Got rid of some evolutionary dead ends.

Example

package com.examples;

import static com.easyjava.EasyJava.*;
import java.util.*;



public class Example {


    @SuppressWarnings({"unchecked", "unused"})
    public static void main(String [] args) {
        Map<String, Integer> tel;

        //tel = {'jack': 4098, 'sape': 4139}
        tel = mp("jack", 4098, "sape", 4139);

        //tel['guido'] = 4127
        tel.put("guido", 4127);

        //print (tel)
        print(tel);
        //Output {'sape': 4139, 'guido': 4127, 'jack': 4098}

        // print (tel['jack'])
        print(tel.get("jack"));
        //Output 4098

        // del tel['sape']
        tel.remove("sape");


        // tel['irv'] = 4127
        tel.put("irv", 4127);


//      print(tel)
        print(tel);
//      Output {'guido': 4127, 'irv': 4127, 'jack': 4098}

//      print(tel.keys())
        print (tel.keySet());
//      Output ['guido', 'irv', 'jack']


//      'guido' in tel
        print (tel.containsKey("guido"));
//      Output True


//      tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
        tel = dict(kv("sape", 4139), kv("guido", 4127), kv("jack", 4098)); //get unchecked exception for Java 6 but not Java 7
//      print (tel)
        print(tel);
//      Output {'sape': 4139, 'jack': 4098, 'guido': 4127}


        //List Comprehension
         Class <?> c = Example.class;


//      print( dict([(x, x**2) for x in (2, 4, 6)]) )     # use a list comprehension
//      Output {2: 4, 4: 16, 6: 36}
        print (map(fn(c, "pow2"), list(2, 4, 6)));

//      >>> for i, v in enumerate(['tic', 'tac', 'toe']):
//          ...     print i, v
//          ...
//          0 tic
//          1 tac
//          2 toe
        enumerate(fn(c, s.printItem), list("tic", "tac", "toe"));

        //You can also declare functions on the fly like so
        class Foo {
            void printItem(int i, String v) {
                print("foo", i , v);
            }           
        }
        enumerate(fn(new Foo(), s.printItem), list("tic", "tac", "toe"));

//      >>> def f(x): return x % 2 != 0 and x % 3 != 0
//              ...
//      >>> filter(f, range(2, 25))
//          [5, 7, 11, 13, 17, 19, 23]      

        class Filter {
            boolean f(int x) {
                return x % 2 != 0 && x % 3 != 0;
            }           
        }
        print (filter(f(new Filter()), range(2, 25)));

        Collection<?> objitems = filter(f(new Filter()), range(2, 25));
        Collection<Integer> myitems = gfilter(f(new Filter()), range(2, 25));

        print (myitems, objitems);

//      >>> def cube(x): return x*x*x
//              ...
//      >>> map(cube, range(1, 11))
//      [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

        print (map(fn(c, s.cube), range(1,11)));
        List<?> list = map(fn(c, s.cube), range(1,11));
        List<String> gmap = gmap(fn(String.class, c, s.stringize), range(1,11));
        print (list, gmap);

//      >>> def add(x,y): return x+y
//              ...
//      >>>      reduce(add, range(1, 11))
//      55

        print ( reduce(fn(c,s.add), range(1,11)) );
        Object object = reduce(fn(c,s.add), range(1,11));
        int greduce = greduce(fn(Integer.class, c,s.add), range(1,11));
        int greduce2 = greduce(fn(c,s.add), range(1,11));
        print(object, greduce, greduce2);
    }

    static int add(int x, int y) {
        return x + y;
    }

    static int cube(int i) {
        return i * i * i;
    }

    static int pow2(int i) {
        return i * i;
    }

    static String stringize(int i) {
        switch (i) {
        case 1:
            return "one";
        case 2:
            return "two";
        case 3:
            return "three";
        default:
            return "" +i;
        }
    }

    static void printItem(int i, String v) {
        print(i , v);
    }

    static enum s {printItem, cube, add, stringize};


}

Implementation

package com.easyjava;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

public class EasyJava {
    private static Logger log = Logger.getLogger(EasyJava.class.getName());

    // HELPER
    // HELPER

    // HELPER
    // HELPER
    private static Class<?> clazz(Object that) {
        if (that instanceof Class) {
            return (Class<?>) that;
        } else {
            return that.getClass();
        }
    }

    public static void print (Object... items) {
        StringBuilder builder = new StringBuilder(256);
        for (Object item : items) {
            builder.append(item);
            builder.append(' ');
        }
        System.out.println(builder);
    }

    @SuppressWarnings("serial")
    public static class AssertionException extends RuntimeException {

        public AssertionException() {
            super();
        }

        public AssertionException(String message, Throwable cause) {
            super(message, cause);
        }

        public AssertionException(String message) {
            super(message);
        }

        public AssertionException(Throwable cause) {
            super(cause);
        }       
    }

    @SuppressWarnings("serial")
    public static class ReflectionException extends RuntimeException {

        public ReflectionException() {
            super();
        }

        public ReflectionException(String message, Throwable cause) {
            super(message, cause);
        }

        public ReflectionException(String message) {
            super(message);
        }

        public ReflectionException(Throwable cause) {
            super(cause);
        }       
    }

    public static void die(boolean condition, String message) {
        if (condition) {
            throw new AssertionException(message);
        }
    }
    public static void die(String message) {
        throw new AssertionException(message);
    }

    public static void die(String message, Object... args) {
        throw new AssertionException(String.format(message, args));
    }



    // CREATIONAL
    // CREATIONAL

    // CREATIONAL
    // CREATIONAL   
    public static interface Entry<K,V> {
        K key();
        V value();
    }

    private static class EntryImpl<K, V> implements Entry<K, V>{
        EntryImpl(K k, V v) {this.k=k; this.v=v;}
        K k;
        V v;
        @Override
        public K key() {
            return k;
        }
        @Override
        public V value() {
            return v;
        }
    }

    public static <K, V> Entry<K, V> kv (final K k, final V v) {
        return new EntryImpl<K,V>(k, v);
    }

    public static <K, V> Entry <K, V> entry (final K k, final V v) {
        return new EntryImpl<K,V>(k,v);
    }

    public static <V> List<V> list(final V... array) {
        return Arrays.asList(array);
    }

    public static <V> Set<V> set(final V... array) {
        return new HashSet<V>(list(array));
    }

    public static List<Integer> range(int stop) {
        return range(0, stop);
    }

    public static List<Integer> range(int start, int stop) {
        ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
        for (int index=start; index<stop; index++) {
            range.add(index);
        }
        return range;
    }

    public static List<Integer> range(int start, int stop, int inc) {
        ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
        for (int index=start; index<stop; index+=inc) {
            range.add(index);
        }
        return range;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        return map;
    }
    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        map.put(k6, v6);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        map.put(k6, v6);
        map.put(k7, v7);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        map.put(k6, v6);
        map.put(k7, v7);
        map.put(k8, v8);        
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8,
            K k9, V v9) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        map.put(k6, v6);
        map.put(k7, v7);
        map.put(k8, v8);
        map.put(k9, v9);        
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8,
            K k9, V v9, Entry<K,V>...entries) {
        HashMap<K, V> map = new HashMap<K, V>(10 + entries.length);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        map.put(k6, v6);
        map.put(k7, v7);
        map.put(k8, v8);
        map.put(k9, v9);        
        for (Entry<K,V> entry: entries) {
            map.put(entry.key(), entry.value());
        }
        return map;
    }

    public static <K, V> Map<K, V> dict(Entry<K,V>...entries) {
        HashMap<K, V> map = new HashMap<K, V>(5);
        for (Entry<K,V> entry: entries) {
            map.put(entry.key(), entry.value());
        }
        return map;
    }

    //
    // Functional 
    //


    //
    // Functional 
    //
    public static interface Function <T> {
        T execute(Object... params);
    }

    private static class FunctionImpl<T> implements Function<T> {
        Method method;
        Object that;

        FunctionImpl(Class<T> clazz, Method method, Object that) {
            this.method=method; 
            this.that = that;
        }


        @SuppressWarnings("unchecked")
        public T execute(Object... params) {
            try {
                return (T) method.invoke(that, params);
            } catch (Exception ex) {

            }
            return null;
        }

    }


    public static <T> Function<T> f(Class<T> returnType, Object that, Object... args) {
        try {
            return fn(returnType, that, "f", args);
        } catch (Exception e) {
            throw new ReflectionException(e);
        }
    }

    public static Function<?> f(Object that, Object... args) {
        try {
            return fn(that, "f", args);
        } catch (Exception e) {
            throw new ReflectionException(e);
        }
    }

    public static Function<?> fn(Object that, Object name, Object... args) {
        return fn(Object.class, that, name, args);
    }

    public static <T> Function<T> fn(Class<T> returnType, Object that, Object name, Object... args) {
        try {
            Method[] methods = clazz(that).getDeclaredMethods();
            for (Method m : methods) {
                if (args.length <= m.getParameterTypes().length) {
                    if (m.getName().equals(name.toString())) {
                        m.setAccessible(true);
                        if (Modifier.isStatic(m.getModifiers())) {
                            return new FunctionImpl<T>(returnType, m, null);
                        } else {
                            return new FunctionImpl<T>(returnType, m, that);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.log(Level.SEVERE, String.format("Unable to find function that=%s, name=%s, args=%s", that, name, list(args)), ex);
        }
        die("Unable to find function that=%s, name=%s, args=%s", that, name, list(args));
        return null;
    }

    public static void enumerate(Function<?> f, Collection<?> c) {
        int index = 0;
        for (Object o : c) {
            f.execute(index, o);
            index++;
        }
    }

    public static Collection<?> filter(Function<?> f, List<?> l) {
        return gfilter(f,l);
    }

    public static Collection<?> filter(Function<?> f, Collection<?> c) {
        return gfilter(f, c);
    }

    public static <T> Collection<T> gfilter(Function<?> f, List<T> l) {
        ListIterator<?> listIterator = l.listIterator();
        while (listIterator.hasNext()) {
            Boolean b = (Boolean) f.execute(listIterator.next());
            if (!b) {
                listIterator.remove();
            }
        }
        return l;
    }

    public static <T> Collection<T> gfilter(Function<?> f, Collection<T> c) {
        ArrayList<Object> removeList = new ArrayList<Object>(c.size());
        for (Object o : c) {
            Boolean b = (Boolean) f.execute(0);
            if (!b) {
                removeList.add(o);
            }           
        }
        for (Object o: removeList) {
            c.remove(o);
        }
        return c;
    }


    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List<?> map(Function f, Collection<?> c) {
        return gmap(f, c);
    }

    public static <IN, OUT> List<OUT> gmap(Function<OUT> f, Collection<IN> c) {
        ArrayList<OUT> mapList = new ArrayList<OUT>(c.size());
        for (Object o : c) {
            mapList.add(f.execute(o));
        }
        return mapList;
    }

    @SuppressWarnings("rawtypes")
    public static Object reduce(Function f, Collection<?> c) {
        return greduce(f, c);
    }

    @SuppressWarnings("unchecked")
    public static <T> T greduce(Function<?> f, Collection<T> c) {
        T accumulo = null;
        int index=0;
        for (T o : c) {
            if (index==0) {
                accumulo = o;
            } else {
                accumulo = (T) f.execute(accumulo, o);
            }
            index++;
        }
        return accumulo;
    }


}

Functional Programming with EasyJava

Functional programming with EasyJava

EasyJava is this idea I had, whereby, you make Java as easy as you can. It does not have Map literals or List literals, but with varargs, static imports, and some imagination You can get pretty close in size and expressivness. In the last blog bost I showed some examples of this. I've started with Python and just seeing what I can implement that is close in Java. My goal is less is more.

For this to make a lot of sense you need to see the previous post on this.

There is some Java boilerplate code, but we only have to do this once.

Get the class that will hold the "functions" for this

    Class <?> c = Example.class;

Python list comprehension

    print( dict([(x, x**2) for x in (2, 4, 6)]) )

Easy Java equivalent

    print ( dict(fn(c, "pow2"), list(2, 4, 6) ));

First thing to notice is that the Java version is about the same size as Python version, except that it is not because we have to define the function as follows.

pow2 "function"

static int pow2(int i) {
    return i * i;
}

The pow2 funciton is static because we are using this example code from main. If we were using pow2 from an instance method, then it could be defined as.

pow2 "function"

int pow2(int i) { return i * i; }

The you would use it as follows from within a instacne method.

Using fn with instance methods.

    print ( dict(fn(this, "pow2"), list(2, 4, 6) ));

The fn function is defined in EasyJava (Read first blog post).

    dict( fn(this, "pow2"), list(2, 4, 6) );

The first argument to dict is the function to apply to each member of the list. The sencond argume is the list. The funciton list, turns its arguments into a ArrayList<T> where T is the type of argument you past to list.

Output of Python list comprehension versus EasyJava equiv

    {2: 4, 4: 16, 6: 36}
    {2=4, 4=16, 6=36}

I've added a method called enumerate, which was inspired by Python's enumerate, but took a sharp 90 degree turn away.

Output of Python enumerate

    >>> for i, v in enumerate(['tic', 'tac', 'toe']):
        ...     print (i, v)
        ...
        0 tic
        1 tac
        2 toe

EasyJava enumerate takes a function

    enumerate(fn(c, s.printItem), list("tic", "tac", "toe"));

The enumerate takes a funciton which is created with a fn. The fn takes the a class (c), and a name (s.printItem). The name can be any object as fn just calls toString on it. This means you can use Java Enums as follows.

static enum s {printItem, cube, add};

This way if you use a function over and over, you don't have to worry about misspelling it, and you get code completiion.

The printItems is defined as follows:

static void printItem(int i, String v) {
    print(i , v);
}

Of course one could imagine it be defined like this:

void printItem(int i, String v) { print(i , v); }

The output of the Java version is as follows:

Output of enumerate example EasyJava

0 tic 
1 tac 
2 toe

The Java version is more verbose mostly due to the fact that there are no closures in Java yet. (There will be in Java 8.)

Python and EasyJava filter

Python filter

    def f(x): return x % 2 != 0 and x % 3 != 0
    print(filter(f, range(2, 25)))

Easy Java Filter

    class Filter { boolean f(int x) {
        return x % 2 != 0 && x % 3 != 0;
    }}
    print (filter(f(new Filter()), range(2, 25)));

The output is near identical. Notice the introduction of the f fucntion which is like fn, except is always looks for a method named f.

I also added a range function to EasyJava that is similar to Pythons.

Python map versus EasyJava map

Python map

    def cube(x): return x*x*x
    print( map(cube, range(1, 11)) )

Python map output

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

EasyJava map

    static int cube(int x) { return x*x*x;}
    ...
    print (map(fn(c, s.cube), range(1,11)));

Java map output

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

Python reduce versus EasyMap reduce

Python reduce

def add(x,y): return x+y
print ( reduce(add, range(1, 11)) )

Python reduce output

55

EasyJava reduce

static int add(int x, int y) {return x + y;}
...
print ( reduce(fn(c,s.add), range(1,11)) );

EasyJava reduce output

55

Wednesday, June 6, 2012

Easy Java, scratching an itch

Easy Java

I have had this itch for a while. I love to work in languages like Python and Groovy, but seem to do a lot of Java development. It pays the bills as it were. To me, it would be nice to have some of language features from Python and Groovy in Java.

Literals for Maps, Lists, some functional programming, some dynamic method invocation here and there.

I starter scratching my itch a bit when I worked on Crank a few years ago. I created a DAO framework with a DSL like criteria in Java. Mostly using vargs and such.

My main focus is going to be on Python, then maybe take a look at Groovy and Ruby and see what can be done. This will all be Java language constructs. Nothing really fancy, generics, reflection, static imports, vargs, etc.

The idea is to try to add things like map literals, functional programming, realizing that this is not really possible 100% of the way with Java.

My goal is to under engineering things as much as possilbe and not try to over design things. Easy for the end user developer to use and grok.

Using the Python docs as an inspirataion, there is already some code that is fairly close to its Python example.

Easy Java, Python functions. (Java versus Python)

Java is strongly typed so I have to declare the variable tel.

The code was insprired by the python dictionary docs.

Easy Java versus Python Dictionaries

import static com.easyjava.EasyJava.; import java.util.; public class Example {

public static void main(String [] args) {
    Map<String, Integer> tel;

Python dictionary literal

    tel = {'jack': 4098, 'sape': 4139}

Easy Java Map function

    tel = mp("jack", 4098, "sape", 4139);

They are actually pretty close in size. The function mp is from com.easyjava.EasyJava (not the final name of the project).

Working dictionary in Python

    tel['guido'] = 4127
    print (tel)
    print (tel['jack'])
    del tel['sape']
    tel['irv'] = 4127
    print(tel)
    print(tel.keys())

Working map in Java

    tel.put("guido", 4127);     
    print(tel);
    print(tel.get("jack"));     
    tel.remove("sape");
    tel.put("irv", 4127);
    print(tel);
    print (tel.keySet());

One area where they differ is the in operator.

            print( 'guido' in tel ) #Python
    print( tel.containsKey("guido") ); #Java

I could create a funciton called in that takes two args to make it closer. But, this might be a bit silly. It would look something like:

            print('guido' in tel) #Python
    print (in("guido", tel); #Java

I don't plan on writing my own collection API.

Output for working with dictionary in Python

            {'sape': 4139, 'guido': 4127, 'jack': 4098}
    4098
            {'guido': 4127, 'irv': 4127, 'jack': 4098}
    ['guido', 'irv', 'jack']
    True

Output for working with map in Java

    {sape=4139, jack=4098, guido=4127} 
    4098
    {irv=4127, jack=4098, guido=4127} 
    [irv, jack, guido] 
    true

Python dict function

    tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
    print (tel)

Easy Java dict function

    tel = dict(kv("sape", 4139), kv("guido", 4127), kv("jack", 4098));
    print(tel);

The size is quite close. The dict and kv are static methods.

Output Python then Java

 {'sape': 4139, 'jack': 4098, 'guido': 4127}    
 {sape=4139, jack=4098, guido=4127}

In the next blog post, I will cover list comprehension and functional programming.

But just in case, you can't wait until then.

Here is all of my code with no explanation (implemenation then example code):

EasyJava early prototype

package com.easyjava;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

public class EasyJava {
    private static Logger log = Logger.getLogger(EasyJava.class.getName());

    public static void print (Object... items) {
        StringBuilder builder = new StringBuilder(256);
        for (Object item : items) {
            builder.append(item);
            builder.append(' ');
        }
        System.out.println(builder);
    }

    @SuppressWarnings("serial")
    public static class AssertionException extends RuntimeException {

        public AssertionException() {
            super();
        }

        public AssertionException(String message, Throwable cause) {
            super(message, cause);
        }

        public AssertionException(String message) {
            super(message);
        }

        public AssertionException(Throwable cause) {
            super(cause);
        }       
    }

    @SuppressWarnings("serial")
    public static class ReflectionException extends RuntimeException {

        public ReflectionException() {
            super();
        }

        public ReflectionException(String message, Throwable cause) {
            super(message, cause);
        }

        public ReflectionException(String message) {
            super(message);
        }

        public ReflectionException(Throwable cause) {
            super(cause);
        }       
    }

    public static void die(boolean condition, String message) {
        if (condition) {
            throw new AssertionException(message);
        }
    }
    public static void die(String message) {
        throw new AssertionException(message);
    }

    public static void die(String message, Object... args) {
        throw new AssertionException(String.format(message, args));
    }

    public static interface Entry<K,V> {
        K key();
        V value();
    }

    private static class EntryImpl<K, V> implements Entry<K, V>{
        EntryImpl(K k, V v) {this.k=k; this.v=v;}
        K k;
        V v;
        @Override
        public K key() {
            return k;
        }
        @Override
        public V value() {
            return v;
        }
    }

    public static interface Function {
        Method method();
        Object [] args();
        Object that();
        Object execute(Object... params);
    }

    private static class FunctionImpl implements Function {
        FunctionImpl(Method method, Object [] args, Object that) {this.method=method; this.args=args; this.that = that;}
        Method method;
        Object [] args;
        Object that;


        @Override
        public Method method() {
            return method;
        }

        @Override
        public Object[] args() {
            return args;
        }

        @Override
        public Object that() {
            return that;
        }

        public Object execute(Object... params) {
            try {
                List<Object> paramsList = list(params);
                if (args!=null && args.length > 0) {
                    paramsList.addAll(list(args));
                }
                return method.invoke(that, paramsList.toArray());
            } catch (Exception ex) {

            }
            return null;
        }

    }

    public static <K, V> Entry<K, V> kv (final K k, final V v) {
        return new EntryImpl<K,V>(k, v);
    }

    public static <K, V> Entry <K, V> entry (final K k, final V v) {
        return new EntryImpl<K,V>(k,v);
    }

    public static <V> List<V> list(V... array) {
        return Arrays.asList(array);
    }

    public static <V> Set<V> set(V... array) {
        return new HashSet<V>(list(array));
    }

    public static Function f(Object that, Object... args) {
        try {
            return fn(that, "f", args);
        } catch (Exception e) {
            throw new ReflectionException(e);
        }
    }

    public static Function fn(Object that, Object name, Object... args) {
        try {
            Method[] methods = clazz(that).getDeclaredMethods();
            for (Method m : methods) {
                if (args.length <= m.getParameterTypes().length) {
                    if (m.getName().equals(name.toString())) {
                        m.setAccessible(true);
                        if (Modifier.isStatic(m.getModifiers())) {
                            return new FunctionImpl(m, args, null);
                        } else {
                            return new FunctionImpl(m, args, that);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.log(Level.SEVERE, String.format("Unable to find function that=%s, name=%s, args=%s", that, name, list(args)), ex);
        }
        die("Unable to find function that=%s, name=%s, args=%s", that, name, list(args));
        return null;
    }

    private static Class<?> clazz(Object that) {
        if (that instanceof Class) {
            return (Class<?>) that;
        } else {
            return that.getClass();
        }
    }
    public static Map<Object, Object> dict(Function f, Collection<?> c) {
        HashMap<Object, Object> map = new HashMap<Object, Object>(5);
        for (Object o : c) {
            map.put(o, f.execute(o));
        }
        return map;
    }
    public static <K, V> Map<K, V> mp(K k0, V v0) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        return map;
    }
    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
        HashMap<K, V> map = new HashMap<K, V>(10);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        return map;
    }

    public static <K, V> Map<K, V> mp(K k0, V v0, K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, Entry<K,V>...entries) {
        HashMap<K, V> map = new HashMap<K, V>(10 + entries.length);
        map.put(k0, v0);
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        for (Entry<K,V> entry: entries) {
            map.put(entry.key(), entry.value());
        }
        return map;
    }

    public static <K, V> Map<K, V> dict(Entry<K,V>...entries) {
        HashMap<K, V> map = new HashMap<K, V>(5);
        for (Entry<K,V> entry: entries) {
            map.put(entry.key(), entry.value());
        }
        return map;
    }

    public static void enumerate(Function f, Collection<?> c) {
        int index = 0;
        for (Object o : c) {
            f.execute(index, o);
            index++;
        }
    }

    public static Collection<?> filter(Function f, List<?> l) {
        ListIterator<?> listIterator = l.listIterator();
        while (listIterator.hasNext()) {
            Boolean b = (Boolean) f.execute(listIterator.next());
            if (!b) {
                listIterator.remove();
            }
        }
        return l;
    }

    public static Collection<?> filter(Function f, Collection<?> c) {
        ArrayList<Object> removeList = new ArrayList<Object>(c.size());
        for (Object o : c) {
            Boolean b = (Boolean) f.execute(0);
            if (!b) {
                removeList.add(o);
            }           
        }
        for (Object o: removeList) {
            c.remove(o);
        }
        return c;
    }

    public static List<Integer> range(int stop) {
        return range(0, stop);
    }

    public static List<Integer> range(int start, int stop) {
        ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
        for (int index=start; index<stop; index++) {
            range.add(index);
        }
        return range;
    }

    public static List<Integer> range(int start, int stop, int inc) {
        ArrayList<Integer> range = new ArrayList<Integer>(stop-start);
        for (int index=start; index<stop; index+=inc) {
            range.add(index);
        }
        return range;
    }

    public static List<?> map(Function f, Collection<?> c) {
        ArrayList<Object> mapList = new ArrayList<Object>(c.size());
        for (Object o : c) {
            mapList.add(f.execute(o));
        }
        return mapList;
    }

    public static Object reduce(Function f, Collection<?> c) {
        Object accumulo = null;
        int index=0;
        for (Object o : c) {
            if (index==0) {
                accumulo = o;
            } else {
                accumulo = f.execute(accumulo, o);
            }
            index++;
        }
        return accumulo;
    }

}

Example using functional programming etc. from EasyJava

package com.examples;

import static com.easyjava.EasyJava.*;
import java.util.*;



public class Example {


    @SuppressWarnings({"unchecked", "unused"})
    public static void main(String [] args) {
        Map<String, Integer> tel;

        //tel = {'jack': 4098, 'sape': 4139}
        tel = mp("jack", 4098, "sape", 4139);

        //tel['guido'] = 4127
        tel.put("guido", 4127);

        //print (tel)
        print(tel);
        //Output {'sape': 4139, 'guido': 4127, 'jack': 4098}

        // print (tel['jack'])
        print(tel.get("jack"));
        //Output 4098

        // del tel['sape']
        tel.remove("sape");


        // tel['irv'] = 4127
        tel.put("irv", 4127);


//      print(tel)
        print(tel);
//      Output {'guido': 4127, 'irv': 4127, 'jack': 4098}

//      print(tel.keys())
        print (tel.keySet());
//      Output ['guido', 'irv', 'jack']


//      'guido' in tel
        print (tel.containsKey("guido"));
//      Output True


//      tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
        tel = dict(kv("sape", 4139), kv("guido", 4127), kv("jack", 4098)); //get unchecked exception for Java 6 but not Java 7
//      print (tel)
        print(tel);
//      Output {'sape': 4139, 'jack': 4098, 'guido': 4127}


        //List Comprehension
         Class <?> c = Example.class;


//      print( dict([(x, x**2) for x in (2, 4, 6)]) )     # use a list comprehension
//      Output {2: 4, 4: 16, 6: 36}
        print (dict(fn(c, "pow2"), list(2, 4, 6)));

//      >>> for i, v in enumerate(['tic', 'tac', 'toe']):
//          ...     print i, v
//          ...
//          0 tic
//          1 tac
//          2 toe
        enumerate(fn(c, s.printItem), list("tic", "tac", "toe"));

        //You can also declare functions on the fly like so
        class Foo {
            void printItem(int i, String v) {
                print("foo", i , v);
            }           
        }
        enumerate(fn(new Foo(), s.printItem), list("tic", "tac", "toe"));

//      >>> def f(x): return x % 2 != 0 and x % 3 != 0
//              ...
//      >>> filter(f, range(2, 25))
//          [5, 7, 11, 13, 17, 19, 23]      

        class Filter {
            boolean f(int x) {
                return x % 2 != 0 && x % 3 != 0;
            }           
        }
        print (filter(f(new Filter()), range(2, 25)));

//      >>> def cube(x): return x*x*x
//              ...
//      >>> map(cube, range(1, 11))
//      [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

        print (map(fn(c, s.cube), range(1,11)));

//      >>> def add(x,y): return x+y
//              ...
//      >>>      reduce(add, range(1, 11))
//      55

        print ( reduce(fn(c,s.add), range(1,11)) );
    }

    static int add(int x, int y) {
        return x + y;
    }

    static int cube(int i) {
        return i * i * i;
    }

    static int pow2(int i) {
        return i * i;
    }

    static void printItem(int i, String v) {
        print(i , v);
    }

    static enum s {printItem, cube, add};


}
Kafka and Cassandra support, training for AWS EC2 Cassandra 3.0 Training