One of the many nice things about Perl is autovivification -- you don't need to assume a hash key exists before you can assign to it, as many times as you like. So you can do something like:
my %employees = (); $employees{'Steve McQueen'}->{salary} = 50000;
And the intermediate hash attached to the key 'Steve McQueen' will be created along the way for you. Now, like a lot of things in Perl this can lead to silent failures -- if I now do this:
my %employees = (); $employees{'Steve Mcqueen'}->{department} = 'Kicking ass'; ^^^
...a whole new hash would be created and the data won't be where I expect. But there are many ways to get around this, most of which you should be doing anyway (case-insensitive keys, IDs as keys, tests, etc.). Perl will let you shoot yourself in the foot.
The equivalent in Java would be:
Map<String,EmployeeData> employees = new HashMap<String,EmployeeData>(); employees.get( "Steve McQueen" ).setSalary( 50000 );
Instead, I need to do:
if ( ! employees.containsKey( "Steve McQueen" ) ) { employees.put( "Steve McQueen", new EmployeeData() ); } employees.get( "Steve McQueen" ).setSalary( 50000 );
Or even more egregious, because all we're asking the language to do is pick a reasonable default implementation of an interface:
Map<Integer,List<Work>> workByID = new HashMap<String,List<Work>>(); Work work = getWorkFromSomewhere();// one line workByID.get( 15 ).add( work );
// ...vs four lines if ( ! workByID.containsKey( 15 ) ) { workByID.put( 15, new ArrayList
() ); } workByID.get( 15 ).add( work );
I know some frameworks do this -- in particular, object creation frameworks that map data coming in (over HTTP, via an XML/JSON graph, etc.) to objects. But should you really need a framework for this, each with its own quirks? (Yes, OGNL, or at least OGNL + Webwork, is quirky.) Shouldn't the language and data structure be smart enough to figure that it can pick a reasonable List implementation for you if there's none specified by use? Or that it can use the no-arg constructor for random JavaBeans?
It winds up encouraging the use of lots of little classes. By itself that's not such a bad thing, I'm a fan of using lots of little classes. But not when most of them do no more than add null checks to the standard library's data structures.
Posted from cwinters.com; read original
I quite like generics but it does seem to involve a lot of headache inducing angle brackets.class AutoVivifyDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : new() {
public new TValue this[TKey key] {
get {
TValue v;
if (this.TryGetValue(key, out v)) {
return v;
} else {
this.Add(key, (v = new TValue()));
return v;
}
}
set {
base[key] = value;
}
}
}