Pregunta

¿Por qué el siguiente fragmento de obra en absoluto? Y qué mal podría ser posible usar este? Pero en serio, ¿hay alguna razón, el código en ${} se evaluó a todos y luego se usa como referencia escalar?

use strict;
no strict 'refs';

our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
¿Fue útil?

Solución

Está bien, a menos que utilice referencias simbólicas . Supongamos el siguiente código:

my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";

De acuerdo, su utilidad no es obvio con scalarrefs, pero es muy útil con arrayrefs.

print "keys: @{[keys %messages]}\n";

Otros consejos

Se explica esto en profundidad en Intermedio Perl .

La sintaxis general para las búsquedas de variables es:

 SIGIL  BLOCK  INDEXY-THING

Para un simple escalar que se parece a:

 print $   { foo };

Probablemente han visto este cuando es necesario separar un nombre de variable de las cosas que lo rodean:

 print "abc${foo}def\n";

Si sólo tiene un identificador de Perl en el bloque y sin ensuciar alrededor, puede dejar fuera de los apoyos, que es el caso común:

 print $foo;

Sin embargo, esto es lo mismo para una referencia de eliminación de referencias:

 SIGIL  BLOCK-RETURNING-REFERENCE  INDEXY-THINGS

Si lo que se obtiene en el bloque es una referencia, Perl intenta eliminar la referencia como pediste también:

 my $ref = \ '12345';
 print $     { $ref };

Esto es un verdadero bloque sin embargo, y no simplemente de azúcar. Puede tener tantas declaraciones como quiera ahí:

 print $     { my $ref = \ '1234'; $ref };

Ahora que no sólo está especificando un identificador de Perl, por lo que Perl no asume que se está dando un identificador y se ejecuta el código y utiliza el resultado como una referencia. Considere la diferencia entre estas declaraciones say casi idénticas:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }

say ${foo};
say ${foo;};

En ese segundo say Perl ve la semi-colon, se da cuenta de que no es un identificador, interpreta el código dentro de las llaves como texto, y devuelve el resultado. Como el resultado es una referencia, se utiliza el ${...} a eliminar la referencia. No importa donde se hace esto, por lo que lo hace dentro de una cadena entre comillas dobles no es especial.

Además, observe la our allí. Eso es importante ahora que vas a considerar algo un poco más complejo:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }
sub baz { 'foo' }

say ${foo};
say ${foo;};
say ${baz;};

Perl intreprets ese último say como código y ve el resultado no es una referencia; que es el foo cadena sencilla. Perl ve que no es una referencia pero ahora en un contexto de eliminación de referencias por lo que hace una referencia simbólica (como Greg tocino describe ). Desde referencias simbólicas trabajan con variables en la tabla de símbolos, que $foo tenía que ser una variable de paquete.

Ya que es fácil de estropear esto, strict tiene una comprobación práctica para ello. Sin embargo, cuando usted lo apaga, no se sorprenda cuando te muerde. :)

Desde el "Uso de referencias a" sección de la documentación perlref :

  

En cualquier lugar que había puesto un identificador (o de la cadena de identificadores) como parte de un nombre de variable o subrutina, se puede reemplazar el identificador con un bloque de devolver una referencia del tipo correcto. En otras palabras, los ejemplos anteriores podrían escribirse así:

$bar = ${$scalarref};
push(@{$arrayref}, $filename);
${$arrayref}[0] = "January";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n");  # iff IO::Handle is loaded
     

Es cierto que es un poco tonto para usar los curlies en este caso, pero el bloque puede contener cualquier expresión arbitraria, en particular, expresiones, subindicadas:

&{ $dispatch{$index} }(1,2,3);    # call correct routine
     

Debido a poder omitir las curlies para el caso simple de $$x, la gente suele cometer el error de visualización de los símbolos de eliminación de referencias como operadores adecuados, y se preguntan acerca de su preferencia. Si lo fueran, sin embargo, usted podría utilizar paréntesis en lugar de aparatos de ortodoncia. Ese no es el caso. Considere la diferencia más adelante; caso 0 es una versión corta a mano de la caja 1, no caso 2:

$$hashref{"KEY"}   = "VALUE";     # CASE 0
${$hashref}{"KEY"} = "VALUE";     # CASE 1
${$hashref{"KEY"}} = "VALUE";     # CASE 2
${$hashref->{"KEY"}} = "VALUE";   # CASE 3
     

Caso 2 también es engañoso en el que está accediendo a una variable llamada %hashref, no eliminación de referencias a través $hashref con el hash que es presumiblemente referencia. Ese sería el caso 3.

Más tarde, en "referencias simbólicas":

  

Nos dijo que las referencias a la existencia de primavera como sea necesario si no están definidos, pero no nos dice lo que sucede si un valor que se utiliza como referencia ya está definido, pero no es una referencia duro. Si lo usa como referencia, que va a ser tratada como una referencia simbólica. Es decir, el valor del escalar se toma para ser el nombre de una variable, en lugar de un enlace directo a un valor (posiblemente) en el anonimato.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top