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:
ex10.pm:
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;
ex10.pl:
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
| [reply] [d/l] |
|
That's exactly what I want, pg++.
| [reply] |
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.
| [reply] [d/l] |
|
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." | [reply] [d/l] |
|
| [reply] [d/l] [select] |
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 | [reply] |
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:
- Tie::StrictHash
- 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];.
Andy
@_="the journeyman larry disciple keeps learning\n"=~/(.)/gs,
print(map$_[$_-77],unpack(q=c*=,q@QSdM[]uRMNV^[ni_\[N]eki^y@))
| [reply] [d/l] [select] |
Re: how to avoid mis-spelling hash keys?
by TheDamian (Vicar) on Jan 05, 2003 at 20:51 UTC
|
| [reply] |
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
| [reply] [d/l] |
Re: how to avoid mis-spelling hash keys?
by adrianh (Chancellor) on Jan 05, 2003 at 21:02 UTC
|
| [reply] |
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.
--
http://fruiture.de
| [reply] |
|
"Inside Out Objects" is indeed the correct term for this
technique.
Abigail
| [reply] |
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 :)
Greetz
Beatnik
... Quidquid perl dictum sit, altum viditur. | [reply] |
|
| [reply] |
|
I think doing approximate string matches for hash keys in
objects would be the programmer's equivalent to playing Russian
Roulette. Bad idea.
| [reply] |
|
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
Greetz
Beatnik
... Quidquid perl dictum sit, altum viditur.
| [reply] |
|
| [reply] |
|
Evil? Me? Surely you're thinking of someone else :)
Is this the talk you mean?
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] |
|
|
|
|
Re: how to avoid mis-spelling hash keys?
by graff (Chancellor) on Jan 05, 2003 at 18:17 UTC
|
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).
| [reply] [d/l] |
|
"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.
| [reply] |
|
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...)
| [reply] |
|
|
|
|
Re: how to avoid mis-spelling hash keys?
by artist (Parson) on Jan 06, 2003 at 07:30 UTC
|
Hi,
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.
Artist
| [reply] |
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. http://www.manning.com/Conway/ | [reply] |