¿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 importedLa 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;
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 ] };