tags:

views:

153

answers:

3

I would like to have a subroutine as a member of a hash which is able to have access to other hash members.

For example

sub setup {
  %a = (
   txt => "hello world",
   print_hello => sub {
    print ${txt};
  })
return %a
}

my %obj = setup();
$obj{print_hello};

Ideally this would output "hello world"

EDIT

Sorry, I failed to specify one requirement

I should be able to do

$obj{txt} = "goodbye";

and then $obj{print_hello} should output goodbye

+2  A: 

This will work:

sub setup { 
    my %a = ( txt => "hello world" );
    $a{print_hello} = sub { print $a{txt} };
    return %a;
}

my %obj = setup();
$obj{print_hello}->();
friedo
thanks for the response, please see edit
Mike
A: 

Close:

sub setup {
  my %a = (
   txt => "hello world",
   print_hello => sub {
    print $a{txt};
  });
  return %a;
}

my %obj = setup();
$obj{print_hello}->();
Oesor
This works as written but makes `%a` a global variable.
mobrule
+7  A: 

If you want the calling code to be able to modify the message in the hash, you need to return the hash by reference. This does what you asked for:

use strict;
use warnings;

sub self_expressing_hash {
    my %h;
    %h = (
        msg              => "hello",
        express_yourself => sub { print $h{msg}, "\n" },
    );
    return \%h;
}

my $h = self_expressing_hash();
$h->{express_yourself}->();

$h->{msg} = 'goodbye';
$h->{express_yourself}->();

However, it's a bizarre concoction -- essentially, a data structure that contains some built-in behavior. Sounds a like an object to me. Perhaps you should look into an O-O approach for your project.

FM
Wouldn't pre-declaring $h, and assigning the hashref to it be simpler? Something like my $h; $h = { msg => 'hello', express_yourself => sub { print $h->{msg}, "\n" } };
MkV
And yes, this is very much like Class::Closure, all it needs is an AUTOLOAD which checks $self{$AUTOLOAD} is a sub ref and adds it to the package symbol table (presuming that setup() is the constructor of a class).
MkV
+1 for mention of object. It's definitely the work of an object.
fengshaun