Stories
Slash Boxes
Comments

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

lachoy (1663)

lachoy
  chris.winters@gmail.com
http://www.cwinters.com/

I am actually Chris Winters; I am actually living in Pittsburgh, Pennsylvania, USA; I am actually married and have three cats. (Guess what one of them is named?) I am the "OpenInteract" guy, which could be good or bad.

Journal of lachoy (1663)

Thursday June 07, 2007
05:19 PM

Collections + Generics = autovivification?

[ #33462 ]

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();

<p>// one line
workByID.get( 15 ).add( work );

<p>// ...vs four lines
if ( ! workByID.containsKey( 15 ) ) {
   workByID.put( 15, new ArrayList<Work>() );
}
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

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • One of the many nice things about Perl is you get to learn cool words like: autovivification.
  • I'm not sure about Java, but C# has a nifty feature where you can add a constraint that the type used must support a public parameterless constructor.

    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)) {