Lo normal es que una expresión como $$a
indique
que $a
es una variable del tipo referencia a un escalar.
Si no fuera el caso, esto es, si $a
no fuera
una referencia, Perl comprueba si $a
contiene
una cadena (esto es, la variable
está en un contexto escalar cadena) y si es el caso usa esa cadena
como nombre de una variable de paquete. Esto se conoce como
referenciado simbolico. Su uso es mas eficiente que la alternativa
de usar eval
. Veamos un ejemplo (obsérvese la ausencia de -w
y
de use strict
):
lhp@nereida:~/Lperl/src/testing$ cat -n symbolicref.pl 1 #!/usr/bin/perl 2 sub data { 3 my ($fa, $sa) = @_; 4 print "Inside data\n"; 5 print "First list: @$fa\n"; 6 print "Second list: @$sa\n"; 7 } 8 9 $data = 4; 10 @data = (1,2,3,4); 11 @tutu = 5..8; 12 $name = "data"; 13 14 print "${$name}\n"; 15 push @{$name}, @data; 16 print "@data\n"; 17 &{$name}('data', 'tutu');La ejecución da como resultado:
lhp@nereida:~/Lperl/src/testing$ symbolicref.pl 4 1 2 3 4 1 2 3 4 Inside data First list: 1 2 3 4 1 2 3 4 Second list: 5 6 7 8
El pragma strict
impide el uso de referencias simbólicas:
$ cat symbol_ref.pl #!/usr/bin/perl -w use strict; our $x = 4; my $a = "x"; $$a = 10; print $x; $ ./symbol_ref.pl Can't use string ("x") as a SCALAR ref while "strict refs" in use at ./symbol_ref.pl line 7.
Se puede ser mas específico y restringir solo el uso de
referencias simbólicas con use strict 'refs'
:
$ cat symbol_ref2.pl #!/usr/bin/perl -w use strict 'refs'; $x = 4; # no se ha usado our $a = "x"; # $a tampoco es declarada $$a = 10; print $x; $ ./symbol_ref2.pl Can't use string ("x") as a SCALAR ref while "strict refs" in use at ./symbol_ref2.pl line 7.
Si, por el contrario, lo que se quiere es permitir el uso
de referenciado simbólico en un segmento del programa sin renunciar al
control que nos da use strict
, debemos usar la cláusula no
:
lhp@nereida:~/Lperl/src$ cat -n symbol_ref3.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 our ($x, $y, $z) = (4, 5, 6); 5 my $a = "x"; 6 { 7 no strict 'refs'; 8 $a = <>; 9 chomp($a); 10 $$a = 10; 11 } 12 13 print "x=$x, y=$y, z=$z\n"; lhp@nereida:~/Lperl/src$ ./symbol_ref3.pl z x=4, y=5, z=10
our
lo son.
Las referencias simbólicas no pueden ser usadas para acceder
a las variables léxicas. Por ejemplo:
#!/usr/bin/perl { my $grain = "headache"; ${"grain"} = "rye"; print "$grain\n"; } print "$grain\n";Imprime la primera vez
headache
y no rye
. Es asi porque la variable
léxica $grain
oculta a la variable de paquete $main::headache
en el ámbito. La salida del programa es:
$ symbolex.pl headache rye
Si la cadena sigue las reglas de un nombre completo, Perl utilizará la tabla de símbolos adecuada:
$name = "General::Specific::data"; print ${$name}; # Lo mismo que: print $General::Specific::data;
Las referencias simbólicas tambien pueden
usarse a la izquierda del operador ->
$symref = "set"; $symref->{type} = "discrete"; # Lo mismo que: $set->{type} = "discrete";
El pragma strict
no protesta del uso de referenciados simbólicos
cuando este se hace mediante el operador ->
.
El ejemplo que sigue muestra un pequeño intérprete. El usuario llama al programa con un comando y un glob que especifica un conjunto de ficheros.
lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_09$ symbolic.pl dirs /p* /pendriver /proc lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_09$ symbolic.pl latest * symbolic.pl lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_09$ symbolic.pl sort_by_time *.pl symbolic.pl simplecalc.pl make_test_files.pl filefilter.pl lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_09$ symbolic.pl chuchu *.pl Unknown command 'chuchu'Para cada comando el programa implanta una función de filtro e imprime el resultado del filtro.
lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_09$ cat -n symbolic.pl 1 #!/usr/local/bin/perl 2 use strict; 3 use warnings; 4 5 main( @ARGV ); 6 7 sub main { 8 die "Usage:\n$0 <command> [file_pattern]\n" unless @_; 9 my $command = shift; 10 11 die "Unknown command '$command'\n" unless main->can( $command ); 12 13 no strict 'refs'; 14 my @r = $command->( @_ ); 15 local $" = "\n"; 16 print "@r\n"; 17 } 18 19 sub sort_by_time { 20 map { $_->[0] } 21 sort { $a->[1] <=> $b->[1] } 22 map { [ $_, -M $_ ] } @_ 23 } 24 25 sub latest { 26 (sort_by_time( @_ ) )[0]; 27 } 28 29 sub dirs { 30 grep { -d $_ } @_; 31 }La principal novedad en este código se refiere al control (línea 11) de que comandos están disponibles. La función can puede ser llamada de la forma:
paquete->can('nombre_de_subrutina')
devuelve cierto si existe una subrutina con ese paquete y falso en caso contrario. De hecho devuelve una referencia (dura/no simbólica) a la subrutina si esta existe.
package
cambia el espacio de nombres
hasta que encontremos una nueva declaración package
,
o hasta el final del bloque actual.
package variables
y lexical variables
.
my
.
package
pertenecen, naturalmente, a un package
(normalmente el actual).
package
inicial es el package main
.
package
pertenece
la variable, puede hacerse prefijando su nombre con el del
package
, separado por ::
.