Wednesday, April 18, 2012

Doto

I've always had an issue with code like this: (event though I do it all the time)

Map map = new HashMap(); //you're forced to create a temporary variable
map.put(1, "one");
map.put(2, "two"); //because you can't chain these void method calls(mutators)
...
return map;
view raw nodoto.java hosted with ❤ by GitHub

Nothing wrong with it, but wouldn't it be nice to be able to chain those calls and avoid declaring that local variable?

I am currently reading "The Joy of Clojure" and came across the doto macro in clojure, which enables you to do the above like so: 
   (doto (new java.util.HashMap) ; or just (java.util.HashMap.)  
         (.put 1 "One")  
         (.put 2 "Two"))  
Nice!  But alas, I am forced to use Java by day so I tried to figure out the best approach to do this.  The first one comes to mind is this:
 new HashMap<Integer, String>(){{  
     put(1, "one");  
     put(2, "Two");  
   }};  

Which works perfectly except that it assumes you are the one constructing the object.  So I tried a more functional approach:
public static <K> Doto<K> doto(K k){
return new Doto(k);
}
public static class Doto<T>{
private T t;
private Doto(T t){
this.t = t;
}
public T DO(FVoid<T> f){
f.apply(t);
return t;
}
}
public interface FVoid<T>{
public void apply(T t);
}
//Which can be used like so :
doto(Maps.<Integer, String>newHashMap()).DO(new FVoid<HashMap<Integer, String>>(){
public void apply(HashMap<Integer, String> map){
map.put(1, "one");
map.put(2, "Two");
}
});
view raw doto.java hosted with ❤ by GitHub


I believe I've gone and made it worse :(

I also tried a js implementation, which is pretty redundant for maps/objects as object literals are built in:
function doto(m, f){f(m); return m;}
//var result = {1: "One", 2: "Two"}
var result = doto({}, function(m){ m[1] = "One"; m[2] = "Two"});
view raw doto.js hosted with ❤ by GitHub


I would love to see some alternate solutions/improvements or maybe event implementations in other languages!