array - ¿Cómo uso referencias simbólicas en Perl?
perl list (7)
En Perl, si una variable contiene el nombre de otra variable, ¿cómo uso la primera variable para visitar la otra?
Por ejemplo, deja
$name = "bob";
@bob = ("jerk", "perlfan");
¿cómo debo usar $ name para saber qué tipo de persona es bob? Aunque no estoy muy seguro, mi vaga memoria me dice que podría estar relacionado con typeglob.
Esta es una muy mala práctica. Si alguna vez necesita hacerlo, significa que debe refactorizar su código. Tal vez un hash con claves nombradas sería mejor:
my %data = (
''bob'' => [ ''jerk'', ''perlfan'' ],
);
my $name = ''bob'';
print $data{ $name }->[0], "/n";
print $data{ $name }->[1], "/n";
my $stringified = join '' and '', @{ $data{ $name } };
print $stringified, "/n";
Por lo general, cuando piense que necesita usar referencias simbólicas, se lo servirá mejor utilizando un hash (matriz asociativa).
use strict;
use warnings;
my %user = (
''bob'' => [qw'' jerk perlfan ''],
''mary'' => ''had a little lamb'',
);
{
for my $name (qw''bob mary susan''){
if( exists $user{$name} ){
if( ref($user{$name}) eq ''ARRAY'' ){
print join( '' '', @{$user{$name}} ), "/n";
}else{
print $name, '' '', $user{$name}, "/n";
}
}else{
print "$name not found/n";
}
}
}
Resultados en:
jerk perlfan mary had a little lamb susan not found
Si cree que realmente necesita usar referencias simbólicas, esta es una forma más segura de hacerlo.
use strict;
use warnings;
# can''t use my
our @bob = ("jerk", "perlfan");
our $mary = ''had a little lamb'';
{
for my $name (qw''bob mary susan''){
if( exists $::{$name} ){
my $ref = $::{$name};
if( *{$ref}{ARRAY} ){
print join('' '',@$ref), "/n";
}elsif( *{$ref}{SCALAR} ){
print "# $name is not an array, it''s a scalar/n";
print $name, '' '', $$ref, "/n";
}
}else{
print "$name not found/n"
}
}
}
Que devuelve:
jerk perlfan # mary is not an array, it''s a scalar mary had a little lamb susan not found
Debe observar que es más difícil para las referencias simbólicas de forma segura, por lo que no debe usarlas.
A menos, por supuesto, que seas un experto haciendo algo avanzado.
Realmente no deberías tener que hacer esto, ver la respuesta de Depesz para la alternativa, pero ...
{
no strict ''refs'';
print join(q{, }, @$name);
}
Sí, puede usar un escalar de cadena como referencia de variable, y busca la variable por su nombre.
También puede hacer esto con typeglobs, consulte el módulo Symbol de una manera sencilla.
Vale la pena evitar las referencias simbólicas, pero si realmente desea usarlas, tienen la misma sintaxis de uso que las referencias regulares: consulte http://perlmonks.org/?node=References+quick+reference .
Ver perldoc -q "variable name"
:
Los principiantes a menudo piensan que quieren tener una variable que contenga el nombre de una variable. ...
Respuesta corta: no. Respuesta larga: lea la entrada de preguntas frecuentes (que también está disponible en su computadora). Respuesta más larga: Lea MJD''s. Por qué es estúpido "usar una variable como nombre de variable" ( Parte 2 , Parte 3 ).
no strict ''refs'';
print "$name is @$name/n";
Varios puntos:
- No estás hablando de typeglobs, estás hablando de referencias simbólicas .
- No use referencias simbólicas: conducen a errores difíciles de rastrear.
- En casi todos los casos en que las referencias simbólicas parecen una buena idea, el mejor enfoque es utilizar una estructura de datos basada en un hash.
- Considera usar Hash :: Util para bloquear tus hash cuando no quieras alterarlos.
- Las referencias simbólicas no funcionan en variables léxicas.
- Typeglobs no funciona en variables léxicas.
- Usa variables léxicas.
- No use referencias simbólicas.
Consulte perlreftut para obtener más información sobre referencias (simbólicas y de otro tipo). Consulte perldsc para obtener ayuda sobre el uso de estructuras de datos. Ver perlmod para más información sobre typeglobs. Vea perlsub para más sobre variables léxicas.
Aquí hay un ejemplo del uso de valores hash bloqueados para controlar el acceso a los datos en función del contenido de una variable:
use strict;
use warnings;
use Hash::Util qw( lock_hash unlock_hash );
my %data;
lock_hash( %data );
#Altering %data is a fatal exception.
unlock_hash( %data );
%data = (
''bob'' => [ ''jerk'', ''genius'' ],
);
lock_hash( %data );
for my $name (qw/ bob margaret /) {
my $info = $data{$name}; # Fatal error when accessing data for margaret.
print "$name is a/n";
print map "/t$_/n", @$info;
}
Dejando a un lado todas las advertencias, la sintaxis para usar referencias simbólicas si necesita usarla (pero no lo hará) es:
use strict;
use warnings;
my $name = ''bob'';
our @bob = qw/jerk genius/;
my $qualities;
{ no strict ''refs'';
print "$name: ", @$name, "/n";
$qualities = /@$name;
}
print "$name is a @$qualities/n";
Tenga en cuenta que la matriz @bob
se declara con our
. Las referencias simbólicas solo funcionan con valores en la tabla de símbolos. En otras palabras, las variables léxicas no funcionan con referencias simbólicas.
En caso de que no lo haya enfatizado lo suficiente, no use referencias simbólicas .