2010-10-02 23 views
6

我認爲這可能使用一個例子來最好問:如何在Perl中序列化閉包?

use strict; 
use warnings; 
use 5.010; 
use Storable qw(nstore retrieve); 

local $Storable::Deparse = 1; 
local $Storable::Eval = 1; 

sub sub_generator { 
    my ($x) = @_; 

    return sub { 
     my ($y) = @_; 
     return $x + $y; 
    }; 
} 

my $sub = sub_generator(1000); 
say $sub->(1); # gives 1001 
nstore($sub, "/tmp/sub.store"); 
$sub = retrieve("/tmp/sub.store"); 
say $sub->(1); # gives 1 

當我傾倒/tmp/sub.store我看到:

$VAR1 = sub { 
      package Storable; 
      use warnings; 
      use strict 'refs'; 
      my($y) = @_; 
      return $x + $y; 
     } 

$x在這個子從未定義。我期望sub_generator生成的子將用$x代替其實際值。我應該如何解決這個問題?

請注意此問題與此one有關。

+0

也許現在是時候回過頭來考慮是否序列化subs是一個好主意?在我的職業生涯中,我很少遇到需要做這樣的事情。 – Ether 2010-10-02 17:08:29

+0

@其他我通過建議使用一個對象。出於某種原因,我傾向於避免使用Perl中的對象,直到你們將我介紹給Moose,這使得每件事都變得更加美好。 – 2010-10-03 13:01:17

回答

5

不幸的是,我認爲Storable不適用於閉包。然而,還有其他CPAN模塊會將封閉系列化。例如。 Data::Dump::Streamer

use 5.012; 
use warnings; 
use Data::Dump::Streamer; 

sub sub_generator { 
    my ($x) = @_; 

    return sub { 
     my ($y) = @_; 
     return $x + $y; 
    }; 
} 

my $sub = sub_generator(1000); 
say $sub->(1); # gives 1001 

my $serialised = Dump($sub)->Out; 
my $copy = do { 
    my $CODE1 = undef; 
    eval $serialised; 
    $CODE1; 
}; 

say $copy->(2); # gives 1002 
say $sub->(1); # still gives 1001 

這是序列化的代碼如下這裏打印時,say Dump $sub;像:

my ($x); 
$x = 1000; 
$CODE1 = sub { 
      use warnings; 
      use strict 'refs'; 
      BEGIN { 
      $^H{'feature_unicode'} = q(1); 
      $^H{'feature_say'} = q(1); 
      $^H{'feature_state'} = q(1); 
      $^H{'feature_switch'} = q(1); 
      } 
      my($y) = @_; 
      return $x + $y; 
     }; 


更新

看到這個線程Storable and Closures在Perl5的搬運工郵件列表。它證實了我對Storable和關閉的看法。

/I3az/

+0

我在做什麼錯?我得到一個空文件:'使用Data :: Dump :: Streamer;我的$ h = {A => 1,B => 2};打開(my $ fh,「>」,「/ tmp/DEL」);轉儲($ h) - >到($ fh)或死亡;關閉($ fh);' – 2010-10-02 11:44:37

+0

'轉儲($ h) - >轉($ fh) - >轉出'將會訣竅。 – draegtun 2010-10-02 13:27:00

+0

謝謝你draegtun。 – 2010-10-02 13:44:00