2010-10-02 16 views
6

myślę, że to może być najlepiej na przykładzie zapytał:Jak serializować zamknięcie w Perlu?

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 

Kiedy zrzucić /tmp/sub.store widzę:

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

Ale $x nigdy nie jest zdefiniowana w tym sub. Spodziewam się, że sub wygenerowany przez sub_generator będzie miał zastąpioną $x swoją rzeczywistą wartością podczas generowania. Jak mam to rozwiązać?

Uwaga: to pytanie dotyczy tego one.

+0

Być może nadszedł czas, aby się cofnąć i zastanowić, czy serializacja subskrypcji jest dobrym pomysłem? Rzadko spotykałem się z koniecznością zrobienia czegoś takiego w mojej karierze. – Ether

+0

@Pozostałem przyjął propozycję użycia obiektu. Z jakiegoś powodu miałem tendencję do omijania przedmiotów w Perlu, dopóki nie przedstawiliście mojego Łosia, co czyni wszystko znacznie przyjemniejszym. –

Odpowiedz

5

Niestety nie sądzę, że Storable współpracuje z zamknięciami. Istnieją jednak inne moduły CPAN, które będą serializować zamknięcie. Na przykład 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 

To właśnie kod odcinkach wygląda po wydrukowaniu tutaj, 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; 
     }; 


Aktualizacja

Zobacz wątek Storable and Closures na perl5 portierzy listy. Potwierdza to, co myślałem o Storable i zamknięciach.

/I3az/

+0

Co robię źle? Dostaję pusty plik: 'use Data :: Dump :: Streamer; mój $ h = {A => 1, B => 2}; open (my $ fh, ">", "/ tmp/DEL"); Dump ($ h) -> To ($ fh) lub umrzeć; close ($ fh); ' –

+0

' Dump ($ h) -> To ($ fh) -> Out' zrobi lew. – draegtun

+0

Dziękuję Draegtun. –