Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

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