2010-06-15 3 views
3

Я хотел бы иметь подпрограмму как член хэша, который может иметь доступ к другим хеш-членам.Perl, «замыкание» с помощью Hash

Например

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

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

В идеале это будет выход "привет мир"

EDIT

К сожалению, я не смог указать одно требование

я должен быть в состоянии сделать

$obj{txt} = "goodbye"; 

, а затем $ OBJ {print_hello} должен вывести goodbye

ответ

7

Если вы хотите, чтобы вызывающий код, чтобы иметь возможность модифицировать сообщение в хеше, вам нужно вернуть хеш по ссылке. Это делает то, что вы просили:

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}->(); 

Однако это странное варево - по существу, структура данных, которая содержит некоторое количество встроенных функций. Звучит как объект для меня. Возможно, вам следует изучить подход O-O для вашего проекта.

+1

Не объявлял бы $ h, а присваивать hashref ему было бы проще? Что-то вроде моего $ h; $ h = {msg => 'hello', express_yourself => sub {print $ h -> {msg}, "\ n"}}; – MkV

+0

И да, это очень похоже на Class :: Closure, все, что ему нужно, это AUTOLOAD, который проверяет $ self {$ AUTOLOAD} - это подрефикс и добавляет его в таблицу символов пакета (предполагая, что setup() является конструктором класс). – MkV

+0

+1 для упоминания объекта. Это определенно работа объекта. – fengshaun

2

Это будет работать:

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

my %obj = setup(); 
$obj{print_hello}->(); 
+0

благодарит за ответ, см. Редактировать – Mike

0

Закрыть:

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

my %obj = setup(); 
$obj{print_hello}->(); 
+1

Это работает как написано, но делает '% a' глобальной переменной. – mob