2010-06-15 61 views
3

我想有一個子例程作爲一個哈希成員,它能夠訪問其他哈希成員。Perl,使用哈希「閉包」

例如

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

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

理想的情況是輸出 「Hello World」 的

編輯

對不起,我沒有指定一個要求

我應該能夠做到

$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 2010-06-15 14:15:22

+0

是的,這非常像Class :: Closure,它需要的是一個AUTOLOAD,它檢查$ self {$ AUTOLOAD}是一個子引用並將其添加到包符號表(假定setup()是構造函數一類)。 – MkV 2010-06-15 14:16:49

+0

提及對象+1。這絕對是一個對象的工作。 – fengshaun 2010-06-15 23:13:49

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 2010-06-15 13:30:24

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 2010-06-15 14:57:22