Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

avoiding hash key typos

by shemp (Deacon)
on Apr 14, 2005 at 23:18 UTC ( #448012=perlquestion: print w/replies, xml ) Need Help??

shemp has asked for the wisdom of the Perl Monks concerning the following question:

Hi all. After spending at least an hour today tracking down why a report i was generating wasnt working correctly, it came down to the fact that i had misspelled a hashkey in one place. This happens way too often, regardless of how careful one is. The report is relatively simple, when particular things occur in the program the values of appropriate hash elements are incremented. So the report hash would look something like this:
%report_hash = ( 'event_1_count' => 17, 'event_2_count' => 53, 'event_3_count' => 1245, ... );
But of course i use meaningful names as the hash keys.

So what sorts of schemes do people use to avoid typos in hash keys? Its a minor annoyance, but takes forever to track down.

Schemes ive used:

  • I have occasionally used constants as keys, but that is annoying to me.
  • Once i wrote a tie called PresetKeysHash. When a hash is tied to this, you pass along an arrayref of 'allowed keys', and if you try to use any other key in that hash, the program bombs
  • I was considering writing a tie that would allow you to register keys on the fly, it would be similar to the PresetKeysHash, but none of this seems quite like what i want.

    Replies are listed 'Best First'.
    Re: avoiding hash key typos
    by dragonchild (Archbishop) on Apr 15, 2005 at 00:08 UTC
    Re: avoiding hash key typos
    by tall_man (Parson) on Apr 15, 2005 at 00:20 UTC
    Re: avoiding hash key typos
    by dave_the_m (Monsignor) on Apr 14, 2005 at 23:47 UTC
      So what sorts of schemes do people use to avoid typos in hash keys?
      use fields qw(a b c);
      This, when used in a module, allows you to write a class that gives you hashes with fixed keys, with a combination of compile-time and run-time constraint checking.


    Re: avoiding hash key typos
    by tlm (Prior) on Apr 15, 2005 at 00:40 UTC

      What I do is treat hashkeys like radioactive waste: I handle them directly as little as possible. If I can programmatically generate them in one way or another, I do. If not, I limit my "direct contact" with them (i.e. cases where I actually type out a hash key) to a single initial typing of the key (usually as one in a list of arguments to qw). (Typing each key once is usually OK; it's when one has to type the same key more than once that troubles begin.)

      For fields of hashref-based objects, I avoid accessing the hash slot directly, and define accessors instead. A mistyped hashkey won't trigger an error from Perl, but a mistyped accessor will.

      If a program's design is such that multiple typing of the same key is unavoidable, I begin thinking about how to restructure the code.

      the lowliest monk

        This is a specific case of a general principle of software design: If you have to do something more than once, abstact it. (put a string in a variable, turn a repeated block of code into a subroutine, put identical subs in multiple scripts into a library, etc.)

        I don't know how extensive your script, but if it is relatively simple, I would avoid using modules and specially designed tie's when the basic tools of the language suffice. Assign the keys to variables once and then use the variables to do hash accesses. If your real code is more complex, you might look at Hash::Util or another appropriate module, or use fields with OO accessors as was already suggested.


        "If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."

        >> I limit my "direct contact" with them (i.e. cases where I actually type out a hash key) to a single initial typing of the key...

        --To address things by names, some people also use OO languages with classes and data members:-).
        (Which are implemented internaly as hashes of course...:-)).
    Re: avoiding hash key typos
    by blahblahblah (Priest) on Apr 15, 2005 at 00:59 UTC
      Using emacs's auto-completion and using descriptive variable (and hash key) names really cuts down my number of typos. In your example, I would probably type "eve" + esc-/ and then cycle through the 3 keys to pick the key that I want.


    Re: avoiding hash key typos
    by Anonymous Monk on Apr 14, 2005 at 23:33 UTC
      use warnings; use strict; my $X; $X->{aa} = 1; my $c = $X->{ab}; print "$c\n";
      I get error: Use of uninitialized value in concatenation (.) at line 6.
        Yep, you sure do.

        Im thinking more along the lines of when a hash key is supposed to be used in more than one place in a script and it is misspelled in one or more of them.

          Note that that error is not directly because the hash key is invalid. This would produce the same error:
          my $c = undef; print "$c\n";
          Anon's sample only emits a warning because it's using the bad value for something that doesn't accept undef's... but if you were doing something like the following, you would get silent failure/undesired results:
          my $ct = $dbh->selectrow_array("SELECT ... WHERE x = ?",{},$c);
        "Use of uninitialized value in concatenation (.) at ..." is not an error. Unfortunately...

        I am used to seeing it quite often; God knows what the code around me does:-). Consider:
        #!/usr/local/bin/perl -w use warnings; use strict; my %report_hash = ( 'event_1_count' => 17, 'event_2_count' => 53, 'event_3_count' => 1245, ); my $salary = $report_hash{'salary'}; print "Conratulations! Your salary this month: $salary dollars.\n"; print "... and my reporting Camel goes on and on...\n"; # Now, this should do it: die "Oops... I did it again!.." unless exists($report_hash{"salary"});
    Re: avoiding hash key typos
    by bugbugbear (Initiate) on Apr 15, 2005 at 14:38 UTC
      There are two options. Either you "lock" the hash, making it illegal to insert, or even look up into the hash with keys you didn't define as legal keys. Or you forbid the use of "magical constants". For decades, we've been saying that code like:
      $var += 42;
      should be avoided - 42 should be put in a meaningful variable (or constant if your language supports that). There's no reason to not apply that logic to string literals as well. If all your hash keys are lexical variables (and you use strict), you get the same benefits that you get if you avoid using package variables. String literals as hash keys are worse than package variables - -w will catch many mistyped package variables, unlike mistyped hash keys.
    Re: avoiding hash key typos
    by shemp (Deacon) on Apr 15, 2005 at 15:23 UTC
      Perhaps a little more clarification on what im doing is in order. (Of course this problem exists everywhere). I write a lot of data migration programs at work, and this problem usually arises when i get some nasty data and have to do all sorts of experimentation just to figure out what to do with the that process goes along i continually modify what is being reported about the process itself. Most of the things being reported are merely counters, but i always end up keeping track of details for various anomolies. During development i find it easiest to just have a hash(ref) that is the main report accumulator, and i throw in whatever needs to be reported. This continually changes. Once the main development / research is complete, i have a good idea of what will ultimately get reported and i can lock down the report accumulator as a class or a hashref if it ends up simplistic.

      One way to help me detect these errors would be to do a Dumper on the report hashref, in addition to the lightly formatted reporting that is going on during development.

      I am quite anal about good programming techniques, this is just one that sometimes gets the best of me. These reporters are what i would consider on the edge of being quick and dirty / needing more formal structure - this probably means that they should probably get the more formal treatment.

      Thanks for all the advice, looking forward to a weekend of studying

    A reply falls below the community's threshold of quality. You may see it by logging in.

    Log In?

    What's my password?
    Create A New User
    Node Status?
    node history
    Node Type: perlquestion [id://448012]
    Front-paged by polettix
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others about the Monastery: (2)
    As of 2020-02-23 14:16 GMT
    Find Nodes?
      Voting Booth?
      What numbers are you going to focus on primarily in 2020?

      Results (102 votes). Check out past polls.