2010-10-02 23 views
6

creo que esto se le puede pedir con un ejemplo:¿Cómo puedo serializar un cierre en 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 

Cuando yo tiro /tmp/sub.store veo:

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

Pero $x Nunca se define en esta sub. Esperaría que el submarino generado por sub_generator tenga $x reemplazado por su valor real en la generación. ¿Cómo debería resolver esto?

Tenga en cuenta que esta pregunta se relaciona con esto one.

+0

Tal vez es hora de dar un paso atrás y considerar si serializar subs es una buena idea? Raramente he encontrado la necesidad de hacer algo así en mi carrera. – Ether

+0

@Ether adopté la sugerencia de usar un objeto en su lugar. Por alguna razón, estaba tratando de evitar objetos en Perl, hasta que ustedes me presentaron mi Moose, lo que hace que todo sea mucho mejor. –

Respuesta

5

Desafortunadamente no creo que Storable funcione con cierres. Sin embargo, hay otros módulos de CPAN que serializarán un cierre. Por ej. 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 

Esto es lo que el código serializado se ve como cuando se imprime aquí, 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; 
     }; 


actualización

Ver este hilo Storable and Closures en el Perl5 porteadores lista de correo. Confirma lo que pensaba sobre Storable y cierres.

/I3az/

+0

¿Qué estoy haciendo mal? Obtengo un archivo vacío: 'use Data :: Dump :: Streamer; my $ h = {A => 1, B => 2}; abierto (mi $ fh, ">", "/ tmp/DEL"); Volcado ($ h) -> A ($ fh) o morir; close ($ fh); ' –

+0

' Dump ($ h) -> To ($ fh) -> Out' hará el truco. – draegtun

+0

Gracias draegtun. –

Cuestiones relacionadas