Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

how to avoid mis-spelling hash keys?

by Gorilla (Sexton)
on Jan 05, 2003 at 18:01 UTC ( [id://224434] : perlquestion . print w/replies, xml ) Need Help??

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

I have run into this problem so many times already, and I believe this must be a common problem among monks.

When I were working on my OO classes, from time to time, I misspelled attribute names (which were hash keys), and then got stuck for hours, trying to find out what was going on.

Is there any way to prevent this from happening? There is a pseudo-hash, but the concept and interface is really stupid.

Replies are listed 'Best First'.
Re: how to avoid mis-spelling hash keys?
by pg (Canon) on Jan 05, 2003 at 18:03 UTC
    Yes, there is a way to avoid this. Starting from Perl 5.8, you can use the lock_keys function provided in Hash:Util package, to lock your attributes, after you initialized them. One example here: package ex10; use Hash::Util; sub new { my $self = {}; $self->{ATTR_ABXCDEFG} = 1; $self->{ATTR_ABCXDEFG} = 2; $self->{ATTR_ABCDXEFG} = 3; $self->{ATTR_ABCDEXFG} = 4; $self->{ATTR_ABCDEFXG} = 5; bless($self); Hash::Util::lock_keys(%{$self}); return $self; } sub do_something_1 { my $self = shift; $self->{ATTR_ABCXDEFG} = 10; } sub do_something_2 { my $self = shift; print $self->{ATTR_ABCXDEFG}; } sub do_something_3 { my $self = shift; $self->{ATTR_AXBCDEFG} = 10; } sub do_something_4 { my $self = shift; print $self->{ATTR_AXBCDEFG}; } 1; use ex10; $e = new ex10; $e->do_something_1; $e->do_something_2; $e->do_something_3; #see what will happen, if you comment out this $e->do_something_4; #try to comment out this
      That's exactly what I want, pg++.
Re: how to avoid mis-spelling hash keys?
by FamousLongAgo (Friar) on Jan 05, 2003 at 18:31 UTC
    Another tack is to wrap the attributes in accessor methods. E.g,
    sub get_attr { $_[0]->{'attr'} } sub set_attr { $_[0]->{'attr'} = $_[1] }
    Now if you misspell an attribute name, it gives you a run-time error.

    Some people hate this approach and call it monkey code, I like it because it documents the object's interface, and lets you change the internal implementation away from a hash if you like. If you really hate writing accessors, consider Class::MethodMaker.

    Whatever else, Damian Conway's book (cited above) is invaluable for OO Perl.

      I like to use AUTOLOAD for my accessors like:
      sub AUTOLOAD { my $self = shift; return unless ref($self); # lets find out what the mysterious missing func is my ($attribute) = $AUTOLOAD =~ m/.*::(.*)/; # this is our psuedo get/set # we can make this as simple or complex as we want if( my $value = shift ){ ### we have an argument # if attribute exists # this is our sort of rudimentary access control # so we can't create arbitrary attributes if( exists $self->{$attribute} ){ $self->{$attribute} = $value; }elsif( exists $self->{ lc($attribute) } ){ # double check caller didn't mean lower case $self->{ lc($attribute) } = $value; }else{ # we can put assignment code here if # we want to be able to automatically # create object attributes on the fly } # here is a good place to call your commit() # or write() method if applicable $self->write(); }else{ # must be an get type call return $self->{$attribute} if exists $self->{$attribute}; return $self->{lc($attribute)} if exists $self->{lc($attribute)}; }# end if/elsif/else value = shift }

      Update: BrentDax is spot on

      "Never be afraid to try something new. Remember, amateurs built the ark. Professionals built the Titanic."
           if( $self­->{$a­ttrib­ute} ){
        That will fail if $self->{$attribute} is set to zero, the empty string, or undef. Perhaps this would work better:

           if(exists $self->{$attribute}) {

        --Brent Dax
        There is no sig.

Re: how to avoid mis-spelling hash keys?
by Hofmator (Curate) on Jan 05, 2003 at 19:07 UTC
    Pre perl 5.8 you can use Tie::Hash::FixedKeys by davorg. It has exactly the functionality you ask for with the drawback of using the tie mechanism which implies a decrease in performance.

    -- Hofmator

Re: how to avoid mis-spelling hash keys?
by aspen (Sexton) on Jan 05, 2003 at 20:24 UTC
    There are a couple of other modules that perform related functionality, that is validating hash keys but also performing additional hash-access checks:
    Provides key checking for references but provides functionality to ensure you don't unintentionally create a new key. Also controls clearing of the Hash.

    Feedback: Strongly-typed "Pascal records" module
    This was a module I just recently posted. It's purpose was to prevent exactly those types of finger-fault errors, but it goes farther in that it allows Perl to ensure you assign the type of data you intended to any particular Hash key. That catches errors such as assigning: $hash{product_list}=$a_product; When what you really meant was: $hash{product_list}=[$a_product];.


    @_="the journeyman larry disciple keeps learning\n"=~/(.)/gs, print(map$_[$_-77],unpack(q=c*=,q@QSdM[]uRMNV^[ni_\[N]eki^y@))
Re: how to avoid mis-spelling hash keys?
by TheDamian (Vicar) on Jan 05, 2003 at 20:51 UTC
Re: how to avoid mis-spelling hash keys?
by perrin (Chancellor) on Jan 05, 2003 at 21:50 UTC
    One very simple approach that works with older versions of Perl is to use lexical variables for your keys.

    use strict; my $bar = 'bar'; my $foo{$bar} = 1; my $foo{$bear} = 1; # gives a compile error
Re: how to avoid mis-spelling hash keys?
by adrianh (Chancellor) on Jan 05, 2003 at 21:02 UTC
Re: how to avoid mis-spelling hash keys?
by fruiture (Curate) on Jan 05, 2003 at 22:41 UTC

    "Inside Out Objects" (at least afaik, they're Abigail-IIs invention) also address and solve this problem. I'm currently doing any Object like that, it makes typos impossible, causing compile time errors.

    Follow this node to get the idea.

    update: correct terminology defined by inventor applied. Thanks to Abigail-II.

      "Inside Out Objects" is indeed the correct term for this technique.


Re: how to avoid mis-spelling hash keys?
by Beatnik (Parson) on Jan 05, 2003 at 18:06 UTC
    You can just abuse String::Approx for approximate string matchings :)

    ... Quidquid perl dictum sit, altum viditur.
      I think doing approximate string matches for hash keys in objects would be the programmer's equivalent to playing Russian Roulette. Bad idea.
        Well, if there is an exact match, it's no roulette. There are quite simple techniques to verify a hash key actually exists. In fact, like janx noted above, there's Tie::Hash::Approx by our very own OeufMayo which does pretty much just that :)

        Tie::Hash::Approx - Approximative match of hash keys using String::Approx

        ... Quidquid perl dictum sit, altum viditur.

        Evil? Me? Surely you're thinking of someone else :)

        Is this the talk you mean?


        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

Re: how to avoid mis-spelling hash keys?
by graff (Chancellor) on Jan 05, 2003 at 18:17 UTC
    I think that
    use fields qw/this_key that_key other_key/;
    might be helpful as well; it was introduced in 5.005, is still present in 5.8, and is described nicely both in it's man page and in Damian Conway's excellent book "Object Oriented Perl" (section 4.3, pp. 130-131).
      "use field" and pseudo hash is definitely what I want to avoid, as it is obsoleted, and the syntax affects the way you coding too much.
        I would agree that the new "Hash::Util::lock_keys()" is a neater approch (pg++), but I didn't see anything in the perl 5.8 man page for "fields" to indicate that it was being depricated -- so where did you hear that it is "obsoleted"? (Just curious. I'm sure this pragma has been used by many who were not so offended by it as you seem to be, and they'd want to know...)
Re: how to avoid mis-spelling hash keys?
by artist (Parson) on Jan 06, 2003 at 07:30 UTC
    Out of box solution would be to use an editor like emacs which provides word completion and u tend to eliminate the problem to some extent.


Re: how to avoid mis-spelling hash keys?
by Anonymous Monk on Jan 07, 2003 at 10:29 UTC
    the "object oriented perl" book discusses this in detail.