• Publicidad

Data::Dumper a fichero y recuperación mediante eval

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Data::Dumper a fichero y recuperación mediante eval

Notapor otronovato » 2013-09-03 13:05 @586

Estoy intentando volcar un hash a un fichero mediante Data::Dumper para recuperarlo después mediante eval().

El código es muy simple:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. open my $ofh, ">", "tmp.txt" || die "Imposible crear tmp.txt\n"; # Inicio de mis pruebas con Data::Dumper                                                                                                          
  2.  
  3. print $ofh Dumper %frecuencias;
  4.  
  5. close $ofh;
  6.  
  7. #Recupero el hash almacenado                                                                                                                                                                                      
  8.  
  9. open my $ifh, "<", "tmp.txt" || die "No puedo leer el archivo tmp.txt\n";
  10. my %rec;
  11.  
  12.  
  13. %rec = eval {<$ifh>};
  14.  
  15.  
  16. close $ifh;
  17.  
  18.  
  19. foreach(sort keys %rec){
  20.  
  21.     my @pos = @{$rec{$_}};
  22.     print "DATOS RECUPERADOS DE ALMACÉN \tGrupos $_ --> ", scalar(@pos), " veces en las posiciones: ", join(',', @pos),"\n";
  23.  
  24.  
  25. }
  26.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Muy simple, pero no funciona. :oops:

El volcado al fichero es correcto:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. xxxxx@xxxxxx:~/Escritorio/scripts_criptografía$ cat tmp.txt  
  2. $VAR1 = 'LA'; 
  3. $VAR2 = [ 
  4.      2, 
  5.      6, 
  6.      14 
  7.     ]; 
  8. $VAR3 = 'AH'; 
  9. $VAR4 = [ 
  10.      3 
  11.     ]; 
  12. $VAR5 = 'AC'; 
  13. $VAR6 = [ 
  14.      7, 
  15.      11 
  16.     ]; 
  17. $VAR7 = 'HO'; 
  18. $VAR8 = [ 
  19.      0, 
  20.      4 
  21.     ]; 
  22. $VAR9 = 'CO'; 
  23. $VAR10 = [ 
  24.       12 
  25.      ]; 
  26. $VAR11 = 'AR'; 
  27. $VAR12 = [ 
  28.       9 
  29.      ]; 
  30. $VAR13 = 'OL'; 
  31. $VAR14 = [ 
  32.       1, 
  33.       5, 
  34.       13 
  35.      ]; 
  36. $VAR15 = 'CA'; 
  37. $VAR16 = [ 
  38.       8 
  39.      ]; 
  40. $VAR17 = 'RA'; 
  41. $VAR18 = [ 
  42.       10 
  43.      ]; 


Pero al recuperarlo:

Sintáxis: [ Descargar ] [ Ocultar ]
  1. xxxxx@xxxxx:~/Escritorio/scripts_criptografía$ ./cripto_lib.pl 
  2. Introduce la cadena a considerar 
  3. holaholacaracola 
  4. Hay 11 tríos de caracteres, que son ACA,ACO,AHO,ARA,CAR,COL,HOL,LAC,LAH,OLA,RAC, 
  5.  
  6.  
  7. Can't use string ("      5, 
  8. ") as an ARRAY ref while "strict refs" in use at ./cripto_lib.pl line 212. 


Como diría el mito de nuestra juventud: "... Ayúdame, Obi Wan Explorer, eres mi única esperanza" :wink:

Un saludo a todos
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Publicidad

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor explorer » 2013-09-03 13:46 @615

Cuando tu hacer

Dumper %frecuencias;

no enviando una variable estás, sino despliegue de esa variable hacer. Por eso, muchos $VARx en archivo aparecer.

Cambiarlo debes:

Dumper \%frecuencias;

De esa manera, volcando un solo valor estamos: referencia a nuestra variable hash ser.

Luego, a hora de leerlo, tu hacer

eval {<$ifh>};

pero el archivo, leer en modo de varias líneas, ser.

Ideal, todo el archivo en una sola variable leer, y luego a eval {} pasar.

Recordar que si dumpeado una referencia tener, eso tendrás.

Usar Data::Dumper::Simple y do(), joven padawan, más simple ser.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor otronovato » 2013-09-03 16:23 @724

El miedo y la ira el reverso oscuro son y yo a punto he estado en algún momento de convertirme en un "shit" :lol: a base de estrellarme contra esta pequeña pieza de código.

Hacerlo quiero y no intentarlo, pero aunque sé que el problema lo tengo con $/ y que tengo que anularla dentro de un bloque, la documentación no acabo de entender. Después de leer tu mensaje sentí una conmoción en la fuerza, como si millones de voces gritaran un instante "¡LO TENGO!" pero ante la realidad de la práctica sólo hubo silencio. (Bueno, tampoco. Mi código ha quedado así:)

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. open my $ofh, ">", "tmp.txt" || die "Imposible crear tmp.txt\n";#Inicio de mis pruebas con Data::Dumper                                                                                                          
  2.  
  3. print $ofh Dumper \%frecuencias;
  4.  
  5. close $ofh;
  6.  
  7. #Recupero el hash almacenado                                                                                                                                                                                      
  8.  
  9. open my $ifh, "<", "tmp.txt" || die "No puedo leer el archivo tmp.txt\n";
  10. my $ref_rec;
  11. my $dato;
  12. my %rec;
  13.  
  14. {
  15.     undef $/;
  16.     my $cadena = <$ifh>;
  17.     $ref_rec = eval {$cadena};
  18. }
  19.  
  20. close $ifh;
  21.  
  22. %rec = %{$ref_rec};
  23.  
  24. foreach(sort keys %rec){
  25.  
  26.     my @pos = @{$rec{$_}};
  27.     print "DATOS RECUPERADOS DE ALMACÉN \tGrupos $_ --> ", scalar(@pos), " veces en las posiciones: ", join(',', @pos),"\n";
  28.  
  29.  
  30. }
  31.  
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4


Y mi intérprete perl rompe el horrísono silencio estelar con este mensaje:

Sintáxis: [ Descargar ] [ Ocultar ]
  1. xxxx@xxxxx:~/Escritorio/scripts_criptografía$ ./cripto_lib.pl 
  2. Introduce la cadena a considerar 
  3. holaholacaracola 
  4. Hay 11 tríos de caracteres, que son ACA,ACO,AHO,ARA,CAR,COL,HOL,LAC,LAH,OLA,RAC, 
  5.  
  6.  
  7. Can't use string ("$VAR1 = { 
  8.      'LA' => [ 
  9.  "...) as a HASH ref while "strict refs" in use at ./cripto_lib.pl line 212. 


He viajado hasta el planeta Dagobah donde el maestro Google me dijo que había que usar el pragma no strict 'refs', pero me parece "hacer trampas". (Y tampoco parece que funcione).

¿Necesito recurrir a armas modernas para estos tiempos menos civilizados como Data::Dumper::Simple y do()?

Que la fuerza y la paciencia te acompañen, maestro :)
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor explorer » 2013-09-03 19:47 @865

Bueno, es cierto que podemos hacer la trampa con poner un

no strict 'vars';

o

no strict 'refs';

pero... es eso: estamos haciendo trampas.

Una solución, también tramposa, es decir que si el error se produce por que Perl no sabe de dónde viene la variable $VAR1, lo que hacemos es declararla en nuestro programa:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.12;
  3. use autodie;
  4. use Data::Dumper;
  5.  
  6. my %frecuencias = (
  7.     A => 1,
  8.     B => [
  9.         1,2,3,
  10.     ],
  11.     C => 'Hola',
  12. );
  13.  
  14. # Guardo el hash
  15.  
  16. open my $ofh, ">", "tmp.txt";
  17. print   $ofh Dumper \%frecuencias;
  18. close   $ofh;
  19.  
  20. # Recupero el hash
  21. my $VAR1;                       # esto es hacer trampas, pero así el modo 'strict' no salta
  22.  
  23. open my $ifh, "<", "tmp.txt";
  24. my $cadena;
  25. {
  26.     local $/;                   # así, sin más, crea una copia local e indefinida, de $/
  27.     $cadena = <$ifh>;
  28. }
  29. close $ifh;
  30.  
  31. eval $cadena;
  32.  
  33. say Dumper $VAR1;               # debe salir lo mismo que %frecuencias
  34. say $VAR1->{C};                 # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Entonces, hacemos el Dumper(), sabemos que en el archivo comienza por un $VAR1 = { ..., así que unas líneas antes declaramos esa variable.

Claro, es un poco tramposo, porque sabemos que el primer Dumper lo hace de esa manera. El caso es que no podemos fiarnos de que siempre sea así.

Entonces, otra solución puede ser. El volcado tiene este aspecto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'A' => 1,
          'C' => 'Hola',
          'B' => [
                   1,
                   2,
                   3
                 ]
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
entonces... lo único que falta ahí... ¡es un my delante!

Pues eso hacemos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4. use Data::Dumper;
  5.  
  6. my %frecuencias = (
  7.     A => 1,
  8.     B => [
  9.         1,2,3,
  10.     ],
  11.     C => 'Hola',
  12. );
  13.  
  14. # Guardo el hash
  15.  
  16. open my $ofh, ">", "tmp.txt";
  17. print   $ofh Dumper \%frecuencias;
  18. close   $ofh;
  19.  
  20.  
  21. # Recupero el hash
  22.  
  23. open my $ifh, "<", "tmp.txt";
  24. my $cadena;
  25. {
  26.     local $/;                   # así, sin más, crea una copia local e indefinida, de $/
  27.     $cadena = <$ifh>;
  28. }
  29. close $ifh;
  30.  
  31. my $hash_ref = eval "my $cadena";       # el 'my' es necesario para que el 'strict' no lo marque como error
  32.                                         # El resultado de eval() es el valor de la última expresión ejecutada.
  33.                                         # Entonces, lo que hemos hecho es:
  34.                                         #
  35.                                         # my($hash_ref) = my($VAR1) = { ... }
  36.  
  37. say Dumper $hash_ref;           # debe salir lo mismo que %frecuencias
  38. say $hash_ref->{C};             # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Ahora, el eval() ya no se come ningún error porque "my $cadena" contiene un trozo de código válido. El problema es ese mini-programa consta solamente de una declaración y definición de una variable: $VAR1. Y resulta que esa variable NO es conocida por nuestro programa (no está declarada en ninguna otra línea). Así que no tenemos acceso a ella.

La solución viene de leer la documentación de eval(): devuelve el valor de la última instrucción ejecutada. Pues bien, la última (y única) instrucción ejecutada por eval() es un my $VAR1 (la asignación de una referencia a un hash). Si eso lo guardamos en una variable "en nuestro lado del universo", seguiremos teniendo una ref. a un hash.

Bueno, todo esto suena muy complicado, así que podemos abreviar algunas cosas. Por ejemplo, todas las líneas encargadas de abrir el archivo en modo lectura, guardarlas a una variable, y luego evaluarlas... todo eso lo hace una función en un solo paso: do().

En la documentación de do() (perldoc -f do) sale esto:
do EXPR
Usa el valor de EXPR como el nombre de un archivo y ejecuta los contenidos del archivo como un script Perl.

do 'stat.pl';

es igual que

eval `cat stat.pl`;

excepto que es más eficiente y conciso, mantiene el nombre del archivo en los mensajes de error, busca en los directorios @INC...

Bueno, pues entonces lo aprovecharemos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4. use Data::Dumper;
  5.  
  6. my %frecuencias = (
  7.     A => 1,
  8.     B => [
  9.         1,2,3,
  10.     ],
  11.     C => 'Hola',
  12. );
  13.  
  14. # Guardo el hash
  15.  
  16. open my $ofh, ">", "tmp.txt";
  17. print   $ofh Dumper \%frecuencias;      # el archivo contiene $VAR1 = { ... }
  18. close   $ofh;
  19.  
  20.  
  21. # Recupero el hash
  22.  
  23. my $hash_ref = do "tmp.txt";    # obtenemos una ref. a un hash
  24.  
  25.  
  26. say Dumper $hash_ref;           # debe salir lo mismo que %frecuencias
  27. say $hash_ref->{C};             # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
El código queda mucho más corto, haciendo lo mismo que antes. Naturalmente, una vez que tenemos $hash_ref, podemos recuperar el hash original con %frecuencias = %{ $hash_ref }, pero te lo he dejado también así, con acceso con referencias, para que veas que no es tan necesario.

ATENCIÓN: realmente, sí son distintos eval() y do(). En concreto, a la hora de re-interpretar el código. do() siempre re-interpreta el código, así que no es aconsejable meterlo dentro de un bucle (se vuelve lento).

Bueno, queda una cosilla suelta... En el archivo de volcado sigue apareciendo la dichosa variable $VAR1. Leyendo la página de manual de Data::Dumper, vemos que podemos dejarlo algo mejor:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4. use Data::Dumper;
  5.  
  6. our %frecuencias = (
  7.     A => 1,
  8.     B => [
  9.         1,2,3,
  10.     ],
  11.     C => 'Hola',
  12. );
  13.  
  14.  
  15. # Guardo el hash
  16.  
  17. open my $ofh, ">", "tmp.txt";
  18. print   $ofh Data::Dumper->Dump([ \%frecuencias ], ['*frecuencias']);   # en el archivo se guarda %frecuencias = ( ...
  19. close   $ofh;
  20.  
  21.  
  22. # Recupero el hash
  23. undef %frecuencias;
  24.  
  25. do "tmp.txt";
  26.  
  27. say Data::Dumper->Dump([ \%frecuencias ], ['*frecuencias']);            # debe salir lo mismo que %frecuencias
  28. say $frecuencias{C};                                                    # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
con lo que ahora, si en el archivo se guarda %frecuencias = ( ... ), al hacer el do(), conseguimos recuperar nuestro hash de forma directa.

Bueno... no tan "directa"... hemos tenido que escribir un montón de cosas "raras" para hacer el volcado con el método Dump().

De toda esa morralla es de la que se encarga Data::Dumper::Simple:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4. use Data::Dumper::Simple;
  5.  
  6. our %frecuencias = (                    # variable global
  7.     A => 1,
  8.     B => [
  9.         1,2,3,
  10.     ],
  11.     C => 'Hola',
  12. );
  13.  
  14.  
  15. # Guardo el hash
  16.  
  17. open my $ofh, ">", "tmp.txt";
  18. print   $ofh Dumper %frecuencias;       # en el archivo se guarda %frecuencias = ( ...
  19. close   $ofh;
  20.  
  21.  
  22. # Recupero el hash
  23. undef %frecuencias;
  24.  
  25. do "tmp.txt";
  26.  
  27. say Dumper %frecuencias;        # debe salir lo mismo que %frecuencias
  28. say $frecuencias{C};            # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Y ya tenemos un programa muy limpio.

Como complemento, decir que esto se hace tanto, que desde hace muchos años que existe el módulo Storable, que sirve para "congelar" y "descongelar" variables, a disco:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use Storable;
  4.  
  5. my %frecuencias = (                     # variable global
  6.     A => 1,
  7.     B => [
  8.         1,2,3,
  9.     ],
  10.     C => 'Hola',
  11. );
  12.  
  13.  
  14. # Guardo el hash
  15.  
  16. store \%frecuencias, "tmp.txt";
  17.  
  18.  
  19. # Recupero el hash
  20. undef %frecuencias;
  21.  
  22. my $frecuencias_ref = retrieve "tmp.txt";
  23.  
  24. say $frecuencias_ref->{C};      # 'Hola'
  25.  
  26. %frecuencias = %{ $frecuencias_ref };
  27.  
  28. use Data::Dumper;
  29. say Dumper \%frecuencias;       # debe salir lo mismo que %frecuencias
  30. say $frecuencias{C};            # 'Hola'
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Hay una ventaja clara: con las versiones anteriores con Dump() y Dumper(), se creaba un archivo de más de 220 bytes. Con Storable, se crea un archivo binario de 59 bytes.

Y así termina la lección de hoy.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor otronovato » 2013-09-04 04:55 @247

¡Buenoooo! Voy a necesitar muchas horas para digerir un poco todo ésto.

Por ejemplo, la documentación de Data::Dumper afirma:

Given a list of scalars or reference variables, writes out their contents in perl syntax.


Sin embargo, hemos visto que el resultado de pasar una referencia o una copia de la variable es diferente. como explicabas:

Cuando tu hacer Dumper %frecuencias; no enviando una variable estás, sino despliegue de esa variable hacer. Por eso, muchos $VARx en archivo aparecer.


Se trata de una sutileza que no acabo de comprender. Y por ahora cada vez que intento acceder directamente a la documentación me doy de cabeza con mi falta de conocimientos. En el caso de Data::Dumper, es ver la sintaxis POO y se me cae el alma a los pies. Trabajo, trabajo y trabajo. Estoy en ello. :)

...podemos abreviar algunas cosas. Por ejemplo, todas las líneas encargadas de abrir el archivo en modo lectura, guardarlas a una variable, y luego evaluarlas... todo eso lo hace una función en un solo paso: do().


Entendido.

Bueno, queda una cosilla suelta... En el archivo de volcado sigue apareciendo la dichosa variable $VAR1. Leyendo la página de manual de Data::Dumper, vemos que podemos dejarlo algo mejor:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print   $ofh Data::Dumper->Dump([ \%frecuencias ], ['*frecuencias']);   # en el archivo se guarda %frecuencias = ( ...
  2.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



Absolutamente perdido. Veo lo que hace pero la POO en Perl me resulta extraña por completo. Además me parece que tendré que manejarme con las referencias mucho mejor de lo que lo hago ahora para poder meterme con éso.

# extended usage with names
print Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);


De hecho este ejemplo de la documentación me parece oscuro a más no poder... En la segunda referencia a la lista con los nombres que queremos que tengan las variables volcadas... ¿Qué significa '*ary'?.

Mi código con eval queda finalmente así.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl                                                                                                                                                                                                  
  2.  
  3. use v5.14; #pone a disposición say()                                                                                                                                                                              
  4. use utf8::all;
  5. use warnings;
  6. use strict;
  7. use Data::Dumper;#Given a list of scalars or reference variables, writes out their contents in perl syntax.                                                                                                      
  8. use constant FICH => 'tmp.txt';
  9. require 'cripto_lib.pl';#Librería externa de funciones. Aquí usaremos frec_calc().                                                                                                                                
  10. #Recibe una cadena de caracteres con el mensaje y un escalar con el número                                                                                                                                      
  11. #de caracteres de la subcadena a buscar. Retorna un hash con las subcadenas                                                                                                                                      
  12. #y sus posiciones en la cadena principal                                                                                                                                                                          
  13.  
  14. #El propósito de $0 es aprender a recuperar un hash volcado a fichero                                                                                                                                                  
  15. #mediante la función eval. Una forma primitiva de persistencia                                                                                                                                                    
  16.  
  17.  
  18. @ARGV == 1 ? my $mensaje = uc $ARGV[0] : die "Uso $0 <mensaje>\n";
  19.  
  20. my $ref_hash = &frec_calc( $mensaje, 2);
  21. my $ofh;
  22. my $ifh;
  23. my $ref_dump;
  24. my $cadena;
  25. open $ofh, ">", FICH || die "$!";
  26.  
  27. say $ofh Dumper $ref_hash;#Volcamos una referencia al hash y no el mismo hash                                                                                                                                    
  28. say Dumper $ref_hash;#Compruebo el valor en pantalla                                                                                                                                                              
  29.  
  30. close $ofh;
  31.  
  32. open $ifh, "<", FICH || die "$!";
  33.  
  34. {
  35.     local $/;#Creamos una copia local e indefinida de $/ que almacena el carácter/caracteres de fin de línea.                                                                                                    
  36.     $cadena = <$ifh>;
  37.  
  38. }
  39.  
  40. close $ifh;
  41.  
  42. $ref_dump = eval "my $cadena";
  43. say Dumper $ref_dump;
  44.  
  45. 1;
  46.  
  47.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y mediante do():

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl                                                                                                                                                                                                  
  2.  
  3. use v5.14; #pone a disposición say()                                                                                                                                                                              
  4. use utf8::all;
  5. use warnings;
  6. use strict;
  7. use Data::Dumper;#Given a list of scalars or reference variables, writes out their contents in perl syntax.                                                                                                      
  8. use constant FICH => 'tmp.txt';
  9. require 'cripto_lib.pl';#Librería externa de funciones. Aquí usaremos frec_calc().                                                                                                                                
  10. #Recibe una cadena de caracteres con el mensaje y un escalar con el número                                                                                                                                      
  11. #de caracteres de la subcadena a buscar. Retorna un hash con las subcadenas                                                                                                                                      
  12. #y sus posiciones en la cadena principal                                                                                                                                                                          
  13.  
  14. #El propósito de $0 es aprender a recuperar un hash volcado a fichero                                                                                                                                                  
  15. #mediante la función eval. Una forma primitiva de persistencia                                                                                                                                                    
  16.  
  17.  
  18. @ARGV == 1 ? my $mensaje = uc $ARGV[0] : die "Uso $0 <mensaje>\n";
  19.  
  20. my $ref_hash = &frec_calc( $mensaje, 2);
  21. my $ofh;
  22. my $ifh;
  23. my $ref_dump;
  24. my $cadena;
  25. open $ofh, ">", FICH || die "$!";
  26.  
  27. say $ofh Dumper $ref_hash;#Volcamos una referencia al hash y no el mismo hash                                                                                                                                    
  28. say Dumper $ref_hash;#Compruebo el valor en pantalla                                                                                                                                                              
  29.  
  30. close $ofh;
  31.  
  32. $ref_dump = do 'tmp.txt';
  33. say Dumper $ref_dump;
  34.  
  35. 1;
  36.  
  37.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Cabe destacar que do() no interpreta la constante FICH. Por lo demás funciona de maravilla.

Como siempre gracias. :D

PS: Desde luego, me pondré a hacer las cosas bien mediante Storable.
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor explorer » 2013-09-04 12:58 @582

otronovato escribiste:
explorer escribiste:Cuando tu hacer Dumper %frecuencias; no enviando una variable estás, sino despliegue de esa variable hacer. Por eso, muchos $VARx en archivo aparecer.
Se trata de una sutileza que no acabo de comprender. Y por ahora cada vez que intento acceder directamente a la documentación me doy de cabeza con mi falta de conocimientos.
Se trata de lo siguiente:

Cuando tu tienes un código así:

my $hash_ref = { a => 1, b => 2, c => 3 };

estás declarando una variable escalar, $hash_ref, y la estás definiendo con un valor, que es una referencia a un hash (en este caso, un hash anónimo). La presencia de las llaves determina de lo que estamos hablando (un hash).

En cambio, cuando tenemos:

my %hash = ( 'a', 1, 'b', 2, 'c', 3 );

estamos declarando una variable hash, y la estamos definiendo con unos pares clave/valor. Los paréntesis son los que nos dicen que lo que hay entre ellos es una lista de elementos, que es lo que el hash espera.

Si miras el contenido del Dump, observa cómo está escrito: si con paréntesis o llaves.

otronovato escribiste:
explorer escribiste:Bueno, queda una cosilla suelta... En el archivo de volcado sigue apareciendo la dichosa variable $VAR1. Leyendo la página de manual de Data::Dumper, vemos que podemos dejarlo algo mejor:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print   $ofh Data::Dumper->Dump([ \%frecuencias ], ['*frecuencias']);   # en el archivo se guarda %frecuencias = ( ...
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Absolutamente perdido. Veo lo que hace pero la POO en Perl me resulta extraña por completo. Además me parece que tendré que manejarme con las referencias mucho mejor de lo que lo hago ahora para poder meterme con éso.
Yo te he dicho que ese lío de corchetes y demás está impuesto por el propio módulo Data::Dumper, que lo exige de esa manera. Y por esa razón existe el Data::Dumper::Simple, que simplifica todo ese rollo. De hecho, el módulo es un filtro que traduce nuestro programa a lo que pide Data::Dumper. No hace nada raro, solo eso.

En Perl te encontrarás a veces con cosas así, pero es cosa de la sintaxis de este lenguaje. Ejemplo: [ \%frecuencias ] quiere decir que vamos a sacar una referencia (\) al hash %frecuencias, y ese valor (un escalar) lo metemos como un elemento más de un array anónimo (realmente, solo está ese valor). El array anónimo lo marcan los corchetes. Es como si hubiéramos hecho esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $hash_ref  = \%frecuencias;  # ref. al hash
  2. my @array     = ( $hash_ref );  # un array de un solo elemento
  3. my $array_ref = \@array;        # ref. al array
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
pero, comprimido.

La programación orientada a objetos, en Perl, es sencilla, pero algo primitiva. Hoy se recomienda usar las facilidades que da la distribución Moose. Lo tienes todo explicado en perldoc perlootut, y en la Web (traducido al español).

otronovato escribiste:
# extended usage with names
print Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
De hecho este ejemplo de la documentación me parece oscuro a más no poder... En la segunda referencia a la lista con los nombres que queremos que tengan las variables volcadas... ¿Qué significa '*ary'?
El manual dice que el segundo array de Dump son los nombres de las variables. En caso de variables escalares no hace falta escribir el '$' delante, como es el caso de 'foo'. Y para cuando son nombres de variables que son referencias a arrays y hashes, se debe poner un '*' delante.

En el ejemplo, estamos diciendo que queremos el volcado de las variables $foo y $bar. Y que en vez de las conocidas $VARx, ponga los siguientes nombres: '$foo', y '@ary' o '%ary' (según sea $bar una referencia a un array o un hash).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor otronovato » 2013-09-04 17:51 @785

Gracias por tu ayuda, explorer.

Necesito poner en práctica las cosas que voy aprendiendo para fijarlas, pero, al menos, empiezo a hacerme sensible al especial sabor de Perl. No sé "cocinarlo", pero al menos reconozco el sabor.

En efecto, perldoc muestra:

In the extended usage form, the references to be dumped can be given
user-specified names. If a name begins with a C<*>, the output will
describe the dereferenced type of the supplied reference for hashes and
arrays, and coderefs. Output of names will be avoided where possible if
the C<Terse> flag is set.


Pero no me queda claro: el comportamiento descrito para esta forma de uso extendida... ¿es el mismo que en la forma simple o viene determinado por el añadido del modificador '*'?. Entiendo que Data::Dumper siempre de-referencia arrays y hashes, dado que de lo contrario lo que nos encontraríamos es una dirección de memoria hexadecimal. ¿Correcto?. Sin embargo, más abajo encontramos:

=item I<PACKAGE>->new(I<ARRAYREF [>, I<ARRAYREF]>)

Returns a newly created C<Data::Dumper> object. The first argument is an
anonymous array of values to be dumped. The optional second argument is an
anonymous array of names for the values. The names need not have a leading
C<$> sign, and must be comprised of alphanumeric characters. You can begin
a name with a C<*> to specify that the dereferenced type must be dumped
instead of the reference itself, for ARRAY and HASH references
.


Así que parece que, en su forma extendida este comportamiento ante las referencias sí que viene determinado por el modificador *. Aunque en su forma simple, al volcar una referencia a un hash no encontramos una dirección de memoria.

$Data::Dumper::Purity I<or> I<$OBJ>->Purity(I<[NEWVAL]>)

Controls the degree to which the output can be C<eval>ed to recreate the
supplied reference structures. Setting it to 1 will output additional perl
statements that will correctly recreate nested references. The default is
0.


Entiendo que, a efectos de persistencia debería asignar a '$Data::Dumper::Purity' el valor '1'. ¿Pero qué es '$Data::Dumper::Purity'? ¿Una variable sin más? Aparentemente es suficiente con '$Data::Dumper::Purity=1'.

Un saludo.
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Data::Dumper a fichero y recuperación mediante eval

Notapor explorer » 2013-09-04 18:44 @822

No te líes. Lo del asterisco es solo un truco de notación que el autor del módulo ha elegido para identificar a las variables que son escalares de las que son referencias. Solo es eso: una notación que no tiene nada que ver con la sintaxis del lenguaje.

Sí, con $Data::Dumper::Purity = 1; lo puedes hacer pero también de la forma orientada a objetos: $d->Purity(1).

Las dos formas las tienes en la misma sinopsis del módulo, al principio.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 17 invitados