Link methods to hash values
Herkum
created: 2006-10-01 13:31:51
I have a hash that I would like to get the values for by using subroutine names. Example,
# Hash Value
$hash{'name'} = 'Herk';


$self->get_name(); # Returns 'Herk'
Can someone help me fill in the blank about how I should do this?
Re: Link methods to hash values
created: 2006-10-01 14:12:44

As I understand it, doing it by hand would be something like:

my %hash;

sub get_name {
  my $subname = (caller 0)[3];
  $subname =~ s/.*::get_//;
  print $hash{$subname},v10;
}

$hash{'name'} = 'Herk';
get_name;

But I believe the best way would be to resort to some CPAN module. I haven't done much OO programming but I think [mod://Class::Accessor] will fit.

--
David Serrano

Re: Link methods to hash values
created: 2006-10-01 14:15:35

Now ask the real question (see XY Problem).

It looks like you want to return the 'name' property of an object. Assuming that $hash is the object that was blessed to create the object instance then the following is probably what you want:

sub get_name {
   my $self = shift;
   return $self->{name};
}

DWIM is Perl's answer to Gödel
Re: Link methods to hash values
created: 2006-10-01 15:03:50

Why not simply provide a 'get' method?

$self->get ('name');

...

sub get {
   my ($self, $param) = @_;

   return undef if ! exists $self->{$param};
   return $self->{$param};
}

Alternatively there are CPAN modules such as [mod://Class::MethodMaker] that will generate getters and setters for you given a list of properties.


DWIM is Perl's answer to Gödel
Re^2: Link methods to hash values
created: 2006-10-01 15:08:52

I just wanted to use a more explicit method name rather than pass a value all the time. I figured it, cannot be that hard right?

Let me take a look at Class:MethodMaker and see if that gives me what I want...

Thanks!

Re^3: Link methods to hash values
created: 2006-10-01 15:18:34

If you don't want to use something like [cpan://Class::MethodMaker], it's pretty trivial to do this sort of thing yourself.

package Foo;

use strict;
use warnings;

foreach my $name(qw(foo bar baz quux narf)) { 
    no strict 'refs';
    *{ 'Foo::get_' . $name } = sub { 
        my $self = shift;
        return $self->{$name};
    };
}

Constructing the equivelent set_* methods is left as an exercise for the reader. :)

Re^4: Link methods to hash values
created: 2006-10-01 16:53:10
This looks much easier and cleaner to implement. I am going to put this and see how much I break! :)
Re^5: Link methods to hash values
created: 2006-10-02 04:03:39
much easier and cleaner would be to use Class::Accessor, as Hue-Bond suggested.
Re^2: Link methods to hash values
created: 2006-10-01 19:30:46
return undef if ! exists $self->{$param};

That's more correct (and, in my opinion, readable) as:

return unless exists $self->{$param};

Beware of undef in list context.

Re: Link methods to hash values
created: 2006-10-01 15:06:04

You should probably ask yourself whether this is really the way you want to go. First of all, you don't feel like defining one hundred methods for one hundred hash keys. But say you find a way, you still have at least one hundred different calls, so are you ok with that? It will be very difficult to let your program grow.

Why don't you try to understand 'objects' (that is, blessed references) first, define a getter, a setter and making the key as one of the arguments. The getter and setter methods can validate the input for you.

If you really insist and if you are prepared to follow the narrow, steep, winding path you could use a method called AUTOLOAD; this method will be called in case the requested method can not be found. It allows you to examine the method that was called, so you can extract the desired key from the method. In fact, the O'Reilly book "Perl Objects, References and Modules", chapter 11 (or its successor "Intermediate Perl") describes how to do just what you want.

Re^2: Link methods to hash values
created: 2006-10-01 18:34:48

Luckily friedo made an excellent suggestion Re^3: Link methods to hash values and it was not a lot of work and avoids dealing with the internals of Perl Objects.

Re: Link methods to hash values
created: 2006-10-01 17:36:35
Why just for %hash? why not also for %nifty_hash? Oh, and you might not want this behaviour for %normal_hash.

Solution: make your hashes objects of a class that implements that behaviour. Ah, you are already on that path. I see $self in your code. But how are %hash and $self supposed to be related?

package myHash;

sub new { bless {}, shift }

sub AUTOLOAD {
    # next two lines just to see what's happening...
    print '@_ = ('.join(', ',map{"'$_'"}@_), ")\n";
    print "\$AUTOLOAD = $AUTOLOAD\n";

    my ($self,$value) = @_;
    (my $key = $AUTOLOAD) =~ s/.*:://;
    $self->{$key} = $value if $value;
    $self->{$key};
} 
1;

Now you can

#!/usr/bin/perl
use myHash;
$thingy = myHash->new(foo => 'bar');
print $thingy->foo,"\n";
print $thingy->foo('baz'),"\n";
print $thingy->age('ageless'),"\n";
__END__
#output:
@_ = ('myHash=HASH(0x8166c28)')
$AUTOLOAD = myHash::foo

@_ = ('myHash=HASH(0x8166c28)', 'baz')
$AUTOLOAD = myHash::foo
baz
@_ = ('myHash=HASH(0x8166c28)', 'ageless')
$AUTOLOAD = myHash::age
ageless
@_ = ('myHash=HASH(0x8166c28)')
$AUTOLOAD = myHash::DESTROY

Note the last two lines - since our myHash package doesn't have a method called DESTROY, the AUTOLOAD routine is called to handle DESTROY during global destruction (at program's end). See [doc://perlobj].

But you don't have to roll your own, There are some modules at CPAN which implement autogeneration of accessors, getters/setters (for instance, [mod://Class::Accessor], [mod://Class::MethodMaker], ...), then there's [mod://Spiffy] which provides some other nifty features.

--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Link methods to hash values
created: 2006-10-02 10:53:50
Did you try Class::AutoAccess?

-- Nice photos of naked perl sources here !

perlmonks.org content © perlmonks.org and chromatic, friedo, GrandFather, Herkum, Hue-Bond, jeteve, lyklev, shmem, tinita

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03