Comunicación de Estructuras de Datos Complejas

Marshalling con Data::Dumper

¿Cómo podemos enviar una estructura de datos compleja usando los mecanismos introducidos en las secciones anteriores? Supongamos, por ejemplo, que deseamos comunicar una referencia a un hash cuyos valores son a su vez referencias a arrays, etc.

El módulo Data::Dumper nos da una solución parcial al problema.

nereida:/tmp> perl -MData::Dumper -wde 0
main::(-e:1):   0
  DB<1> $a = [[1,2],[3,4]]
  DB<2> p Dumper $a
$VAR1 = [[ 1,2],[3,4]]; # Aparece $VAR1 =
  DB<3> $Data::Dumper::Terse = 1 
  DB<4> p Dumper $a
[[1,2],[3,4]]        # Eliminamos $VAR1 =

La representación por defecto de Data::Dumper da lugar a problemas con las variables que se autoreferencian:

 DB<26> $h = { name => 'juan' }; $m = { name => 'pedro' }
 DB<27> $h->{hermano} = $m; $m->{hermano} = $h

 DB<28> p Dumper $h
$VAR1 = {'hermano' => {'hermano' => $VAR1,'name' => 'pedro'},'name' => 'juan'};
 DB<30> use strict; eval {$VAR1 = { \
         'hermano' => {'hermano' => $VAR1,'name' => 'pedro'},'name' => 'juan'}\
       }
Variable "$VAR1" is not imported
La solución está en establecer la variable Data::Dumper::Purity a cierto:
 DB<31> $Data::Dumper::Purity=1
 DB<32> p Dumper $h
$VAR1 = {'hermano' => {'hermano' => {},'name' => 'pedro'},'name' => 'juan'};
$VAR1->{'hermano'}{'hermano'} = $VAR1;

Comunicación de Estructuras de Datos Anidadas con Data::Dumper

El siguiente ejemplo muestra como implantar RPC entre procesos usando Data::Dumper:

lhp@nereida:~/Lperl/src/cookbook/ch16$ cat -n sendref.pl
 1  #!/usr/bin/perl -w
 2  use strict;
 3  use Data::Dumper;
 4  use IO::Pipe;
 5  $| = 1;
 6
 7  my $FROM_CHILD = IO::Pipe->new;
 8  my $FROM_FATHER = IO::Pipe->new;
 9
10  my $pid;
11
12  if ($pid = fork) { # Father
13      die "cannot fork: $!" unless defined $pid;
14
15      $FROM_FATHER->writer;
16      $FROM_CHILD->reader;
17
18      my $x = $FROM_CHILD->receive;
19
20      @{$x->{vector}} = map { $_*$_ } @{$x->{vector}};
21
22      $FROM_FATHER->send($x);
23
24      print "Father:\n",Dumper($x);
25
26      close $FROM_CHILD;
27      close $FROM_CHILD;
28      waitpid($pid,0);
29
30  } else { # Child
31      $FROM_FATHER->reader;
32      $FROM_CHILD->writer;
33
34      my $x = { angle => atan2(1, 1), vector => [ 1..10] };
35      $FROM_CHILD->send($x);
36
37      $x = $FROM_FATHER->receive;
38
39      print "Child:\n",Dumper($x);
40
41      close $FROM_CHILD;
42      close $FROM_CHILD;
43      exit;
44  }
45
46  package IO::Pipe::End;
47  use Data::Dumper;
48  use strict;
49
50  sub receive {
51    my $channel = shift;
52
53    my $line;
54    sysread($channel, $line, 1024);
55    chomp($line);
56    return eval($line);
57  }
58
59  sub send {
60    my $channel = shift;
61    my $arg = shift || die "send error: expected a ref\n";
62
63    local $Data::Dumper::Indent = 0;
64    local $Data::Dumper::Terse = 1;
65    local $Data::Dumper::Purity = 1;
66    syswrite($channel, Dumper($arg)."\n");
67  }
68
69  1;
Al ejecutar el programa anterior obtenemos la salida:
lhp@nereida:~/Lperl/src/cookbook/ch16$ sendref.pl
Father:
$VAR1 = {
          'angle' => '0.785398163397448',
          'vector' => [
                        1,
                        4,
                        9,
                        16,
                        25,
                        36,
                        49,
                        64,
                        81,
                        100
                      ]
        };
Child:
$VAR1 = {
          'angle' => '0.785398163397448',
          'vector' => [
                        1,
                        4,
                        9,
                        16,
                        25,
                        36,
                        49,
                        64,
                        81,
                        100
                      ]
        };



Subsecciones
Casiano Rodríguez León
Licencia de Creative Commons
Programación Distribuida y Mejora del Rendimiento
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=44.
2012-06-19