Este es el comando perlreftut que se puede ejecutar en el proveedor de alojamiento gratuito de OnWorks utilizando una de nuestras múltiples estaciones de trabajo en línea gratuitas, como Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS.
PROGRAMA:
NOMBRE
perlreftut: el breve tutorial de Mark sobre referencias
DESCRIPCIÓN
Una de las características nuevas más importantes de Perl 5 fue la capacidad de administrar
estructuras de datos como matrices multidimensionales y hashes anidados. Para habilitarlos, Perl 5
introdujo una característica llamada 'referencias', y el uso de referencias es la clave para administrar
datos complicados y estructurados en Perl. Desafortunadamente, hay mucha sintaxis divertida para
aprender, y la página principal del manual puede ser difícil de seguir. El manual es bastante completo y
A veces, las personas encuentran que eso es un problema, porque puede ser difícil decir qué es importante y
lo que no es.
Afortunadamente, solo necesita saber el 10% de lo que hay en la página principal para obtener el 90% de la
beneficio. Esta página le mostrará ese 10%.
Quién de necesidades Complicado Data Estructuras?
Un problema que surge todo el tiempo es la necesidad de un hash cuyos valores sean listas. Perl tiene
hashes, por supuesto, pero los valores tienen que ser escalares; no pueden ser listas.
¿Por qué querrías un hash de listas? Tomemos un ejemplo simple: tiene un archivo de ciudad
y nombres de países, como este:
Chicago, EE.UU.
Frankfurt, Alemania
Berlín, Alemania
Washington, Estados Unidos
Helsinki, Finlandia
Nueva York, EE.UU.
y desea producir un resultado como este, con cada país mencionado una vez, y luego un
lista alfabética de las ciudades de ese país:
Finlandia: Helsinki.
Alemania: Berlín, Frankfurt.
Estados Unidos: Chicago, Nueva York, Washington.
La forma natural de hacer esto es tener un hash cuyas claves sean nombres de países. Asociado
con cada clave de nombre de país hay una lista de las ciudades de ese país. Cada vez que lees un
línea de entrada, divídala en un país y una ciudad, busque la lista de ciudades ya
se sabe que se encuentra en ese país y agregue la nueva ciudad a la lista. Cuando termines
leyendo la entrada, repita el hash como de costumbre, ordenando cada lista de ciudades antes que usted
imprimirlo.
Si los valores hash no pueden ser listas, pierde. Probablemente tendrías que combinar todas las ciudades
en una sola cadena de alguna manera, y luego, cuando llegara el momento de escribir la salida, tendrías que
divida la cadena en una lista, ordene la lista y conviértala nuevamente en una cadena. Esto es
desordenado y propenso a errores. Y es frustrante, porque Perl ya tiene muy buenas
listas que resolverían el problema si pudieras usarlas.
El sistema Solución
Cuando llegó Perl 5, ya estábamos atascados con este diseño: los valores hash deben
ser escalares. La solución a esto son las referencias.
Una referencia es un valor escalar que se refiere a una matriz completa o un hash completo (o simplemente
sobre cualquier otra cosa). Los nombres son un tipo de referencia con la que ya está familiarizado.
Piense en el presidente de los Estados Unidos: una bolsa desordenada e incómoda de sangre y huesos.
Pero para hablar de él, o representarlo en un programa de computadora, todo lo que necesita es el
cadena escalar fácil y conveniente "Barack Obama".
Las referencias en Perl son como nombres para matrices y hashes. Son privados, internos de Perl.
nombres, por lo que puede estar seguro de que no son ambiguos. A diferencia de "Barack Obama", solo una referencia
se refiere a una cosa, y siempre sabes a qué se refiere. Si tiene una referencia a un
matriz, puede recuperar toda la matriz a partir de ella. Si tiene una referencia a un hash,
puede recuperar todo el hash. Pero la referencia sigue siendo un valor escalar sencillo y compacto.
No puede tener un hash cuyos valores sean matrices; los valores hash solo pueden ser escalares. Eran
atascado con eso. Pero una sola referencia puede referirse a una matriz completa, y las referencias son
escalares, por lo que puede tener un hash de referencias a matrices, y actuará como un hash
de matrices, y será tan útil como un hash de matrices.
Volveremos a este problema de ciudad-país más tarde, después de haber visto algo de sintaxis para
gestión de referencias.
Sintaxis
Solo hay dos formas de hacer una referencia y solo dos formas de usarla una vez que la tenga.
Realizar Referencias
Haz Regla 1
Si pones una "\" delante de una variable, obtienes una referencia a esa variable.
$ aref = \ @array; # $ aref ahora tiene una referencia a @array
$ href = \% hash; # $ href ahora tiene una referencia a% hash
$ sref = \ $ escalar; # $ sref ahora contiene una referencia a $ scalar
Una vez que la referencia se almacena en una variable como $ aref o $ href, puede copiarla o almacenarla
es igual que cualquier otro valor escalar:
$ xy = $ aref; # $ xy ahora tiene una referencia a @array
$ p [3] = $ href; # $ p [3] ahora contiene una referencia a% hash
$ z = $ p [3]; # $ z ahora tiene una referencia a% hash
Estos ejemplos muestran cómo hacer referencias a variables con nombres. A veces quieres
hacer una matriz o un hash que no tenga nombre. Esto es análogo a la forma en que te gusta.
para poder utilizar la cadena "\ n" o el número 80 sin tener que almacenarlo en un nombre
variable primero.
Haz Regla 2
"[ARTÍCULOS]" crea una nueva matriz anónima y devuelve una referencia a esa matriz. "{ ELEMENTOS
} "crea un nuevo hash anónimo y devuelve una referencia a ese hash.
$ aref = [1, "foo", undef, 13];
# $ aref ahora contiene una referencia a una matriz
$ href = {APR => 4, AGO => 8};
# $ href ahora contiene una referencia a un hash
Las referencias que obtiene de la regla 2 son el mismo tipo de referencias que obtiene de la regla
1:
# Esta:
$ aref = [1, 2, 3];
# Hace lo mismo que esto:
@matriz = (1, 2, 3);
$ aref = \ @array;
La primera línea es una abreviatura de las siguientes dos líneas, excepto que no
cree la variable de matriz superflua @array.
Si escribe sólo "[]", obtendrá una nueva matriz anónima vacía. Si escribe solo "{}",
obtener un hash anónimo nuevo y vacío.
Gracias a Referencias
¿Qué puede hacer con una referencia una vez que la tenga? Es un valor escalar y hemos visto
que puede almacenarlo como un escalar y recuperarlo como cualquier escalar. Existen
solo dos formas más de usarlo:
Usa Regla 1
Siempre puede usar una referencia de matriz, entre llaves, en lugar del nombre de una matriz.
Por ejemplo, "@ {$ aref}" en lugar de @array.
Aquí hay algunos ejemplos de eso:
Matrices:
@a @ {$ aref} Una matriz
reverse @a reverse @ {$ aref} Invierte la matriz
$ a [3] $ {$ aref} [3] Un elemento de la matriz
$ a [3] = 17; $ {$ aref} [3] = 17 Asignar un elemento
En cada línea hay dos expresiones que hacen lo mismo. Las versiones de la izquierda funcionan
en la matriz @a. Las versiones de la derecha operan en la matriz a la que hace referencia
$ aref. Una vez que encuentran la matriz en la que están operando, ambas versiones hacen lo mismo para
las matrices.
Usar una referencia hash es exactamente lo mismo:
% h% {$ href} un hash
keys% h keys% {$ href} Obtiene las claves del hash
$ h {'red'} $ {$ href} {'red'} Un elemento del hash
$ h {'red'} = 17 $ {$ href} {'red'} = 17 Asignar un elemento
Lo que quieras hacer con una referencia, Usa Regla 1 le dice cómo hacerlo. Tu solo
escribe el código Perl que habrías escrito para hacer lo mismo con un
matriz o hash, y luego reemplace la matriz o el nombre de hash con "{$ referencia}". "Cómo puedo
recorrer una matriz cuando todo lo que tengo es una referencia? "Bueno, para recorrer una matriz,
escribiría
para mi $ elemento (@array) {
...
}
así que reemplace el nombre de la matriz, @array, con la referencia:
para mi $ elemento (@ {$ aref}) {
...
}
"¿Cómo imprimo el contenido de un hash cuando todo lo que tengo es una referencia?" Primera escritura
el código para imprimir un hash:
para mi $ clave (claves% hash) {
imprimir "$ clave => $ hash {$ clave} \ n";
}
Y luego reemplace el nombre de hash con la referencia:
para mi $ clave (claves% {$ href}) {
imprimir "$ clave => $ {$ href} {$ clave} \ n";
}
Usa Regla 2
Usa Regla 1 es todo lo que realmente necesitas, porque te dice cómo hacer absolutamente todo
alguna vez necesitas hacer con referencias. Pero lo más común que se puede hacer con una matriz o una
hash es extraer un solo elemento, y el Usa Regla 1 la notación es engorrosa. Por lo tanto, allí
es una abreviatura.
"$ {$ aref} [3]" es demasiado difícil de leer, por lo que puede escribir "$ aref -> [3]" en su lugar.
"$ {$ href} {red}" es demasiado difícil de leer, por lo que puede escribir "$ href -> {red}" en su lugar.
Si $ aref contiene una referencia a una matriz, entonces "$ aref -> [3]" es el cuarto elemento de la
formación. No confunda esto con $ aref [3], que es el cuarto elemento de una
matriz diferente, una engañosamente llamada @aref. $ aref y @aref no están relacionados de la misma manera
que $ item y @item son.
De manera similar, "$ href -> {'red'}" es parte del hash al que se refiere la variable escalar $ href,
quizás incluso uno sin nombre. $ href {'red'} es parte del hash% href con nombre engañoso.
Es fácil olvidarse de omitir el "->" y, si lo hace, obtendrá resultados extraños cuando
su programa obtiene elementos de matriz y hash de hashes y matrices totalmente inesperados que
no eran los que querías usar.
An Ejemplo
Veamos un ejemplo rápido de la utilidad de todo esto.
Primero, recuerde que "[1, 2, 3]" crea una matriz anónima que contiene "(1, 2, 3)" y
le da una referencia a esa matriz.
Ahora piensa en
@a = ([1, 2, 3],
[4, 5, 6],
[7, 8, 9]
);
@a es una matriz con tres elementos y cada uno es una referencia a otra matriz.
$ a [1] es una de estas referencias. Se refiere a una matriz, la matriz que contiene "(4, 5,
6) ", y como es una referencia a una matriz, Usa Regla 2 dice que podemos escribir
$ a [1] -> [2] para obtener el tercer elemento de esa matriz. $ a [1] -> [2] es el 6. De manera similar,
$ a [0] -> [1] es el 2. Lo que tenemos aquí es como una matriz bidimensional; puedes escribir
$ a [FILA] -> [COLUMNA] para obtener o establecer el elemento en cualquier fila y columna de la matriz.
La notación todavía parece un poco engorrosa, por lo que hay una abreviatura más:
flecha Regla
Entre dos subíndices, la flecha es opcional.
En lugar de $ a [1] -> [2], podemos escribir $ a [1] [2]; Significa lo mismo. En vez de
"$ a [0] -> [1] = 23", podemos escribir "$ a [0] [1] = 23"; Significa lo mismo.
¡Ahora realmente parece matrices bidimensionales!
Puedes ver por qué las flechas son importantes. Sin ellos, hubiéramos tenido que escribir
"$ {$ a [1]} [2]" en lugar de $ a [1] [2]. Para matrices tridimensionales, nos dejan escribir
$ x [2] [3] [5] en lugar del ilegible "$ {$ {$ x [2]} [3]} [5]".
Solución
Aquí está la respuesta al problema que planteé anteriormente, de reformatear un archivo de ciudad y
nombres de países.
1 mi tabla de%;
2 mientras (<>) {
3 mordiscos;
4 my ($ ciudad, $ país) = split /, /;
5 $ tabla {$ país} = [] a menos que exista $ tabla {$ país};
6 push @ {$ table {$ country}}, $ city;
7}
8 para cada $ país (tabla de% de claves de ordenación) {
9 imprimir "$ país:";
10 mis @ciudades = @ {$ tabla {$ país}};
11 imprimir unión ',', ordenar @ciudades;
12 imprimir ". \ N";
13}
El programa tiene dos partes: las líneas 2 a 7 leen la entrada y construyen una estructura de datos, y
las líneas 8-13 analizan los datos e imprimen el informe. Vamos a tener una tabla hash,%
cuyas claves son nombres de países y cuyos valores son referencias a matrices de nombres de ciudades.
La estructura de datos se verá así:
%mesa
+ ------- + --- +
| | | + ----------- + -------- +
| Alemania | * ----> | Frankfurt | Berlín |
| | | + ----------- + -------- +
+ ------- + --- +
| | | + ---------- +
| Finlandia | * ----> | Helsinki |
| | | + ---------- +
+ ------- + --- +
| | | + --------- + ------------ + ---------- +
| USA | * ----> | Chicago | Washington | Nueva York |
| | | + --------- + ------------ + ---------- +
+ ------- + --- +
Primero veremos la salida. Suponiendo que ya tenemos esta estructura, ¿cómo la imprimimos?
¿fuera?
8 para cada $ país (tabla de% de claves de ordenación) {
9 imprimir "$ país:";
10 mis @ciudades = @ {$ tabla {$ país}};
11 imprimir unión ',', ordenar @ciudades;
12 imprimir ". \ N";
13}
% table es un hash ordinario, y obtenemos una lista de claves de él, ordenamos las claves y repetimos
sobre las teclas como de costumbre. El único uso de referencias está en la línea 10. $ table {$ country} looks
sube la clave $ country en el hash y obtiene el valor, que es una referencia a una matriz de
ciudades de ese país. Usa Regla 1 dice que podemos recuperar la matriz diciendo
"@ {$ table {$ country}}". La línea 10 es como
@ciudades = @array;
excepto que el nombre "matriz" ha sido reemplazado por la referencia "{$ tabla {$ país}}". El
"@" le dice a Perl que obtenga la matriz completa. Habiendo obtenido la lista de ciudades, la ordenamos,
únete a él e imprímelo como de costumbre.
Las líneas 2-7 son responsables de construir la estructura en primer lugar. Aquí están
nuevo:
2 mientras (<>) {
3 mordiscos;
4 my ($ ciudad, $ país) = split /, /;
5 $ tabla {$ país} = [] a menos que exista $ tabla {$ país};
6 push @ {$ table {$ country}}, $ city;
7}
Las líneas 2-4 adquieren un nombre de ciudad y país. La línea 5 busca ver si el país ya está
presente como clave en el hash. Si no es así, el programa usa la notación "[]" (Haz Regla
2) para fabricar una nueva matriz de ciudades anónima y vacía, e instala una referencia a ella
en el hash bajo la clave apropiada.
La línea 6 instala el nombre de la ciudad en la matriz adecuada. $ table {$ country} ahora tiene una
referencia a la variedad de ciudades vistas en ese país hasta ahora. La línea 6 es exactamente como
empujar @array, $ ciudad;
excepto que el nombre "matriz" ha sido reemplazado por la referencia "{$ tabla {$ país}}". El
"push" agrega un nombre de ciudad al final de la matriz a la que se hace referencia.
Hay un buen punto que me salté. La línea 5 es innecesaria y podemos deshacernos de ella.
2 mientras (<>) {
3 mordiscos;
4 my ($ ciudad, $ país) = split /, /;
5 #### $ tabla {$ país} = [] a menos que exista $ tabla {$ país};
6 push @ {$ table {$ country}}, $ city;
7}
Si ya hay una entrada en la tabla% para el $ país actual, entonces nada es diferente.
La línea 6 ubicará el valor en $ table {$ country}, que es una referencia a una matriz, y
empuje $ city en la matriz. Pero, ¿qué hace cuando $ country tiene una clave, digamos "Grecia",
que aún no está en la tabla%?
Esto es Perl, por lo que hace exactamente lo correcto. Ve que quieres presionar "Atenas"
en una matriz que no existe, por lo que ayuda a crear una matriz nueva, vacía y anónima para
usted, lo instala en% table y luego inserta "Athens" en él. Se llama
'autovivificación': dar vida a las cosas automáticamente. Perl vio que la clave no era
en el hash, por lo que creó una nueva entrada de hash automáticamente. Perl vio que querías usar
el valor hash como una matriz, por lo que creó una nueva matriz vacía e instaló una referencia a
en el hash automáticamente. Y como de costumbre, Perl hizo que la matriz fuera un elemento más larga
mantenga el nombre de la nueva ciudad.
El sistema resto
Prometí darte el 90% del beneficio con el 10% de los detalles, y eso significa que me fui
90% de los detalles. Ahora que tiene una descripción general de las partes importantes, debería
Será más fácil leer la página del manual de perlref, que analiza el 100% de los detalles.
Algunos de los aspectos más destacados de perlref:
· Puede hacer referencias a cualquier cosa, incluidos escalares, funciones y otros
Referencias.
· En Usa Regla 1, puede omitir los corchetes siempre que el elemento dentro de ellos sea un
variable escalar atómica como $ aref. Por ejemplo, @ $ aref es lo mismo que "@ {$ aref}" y
$$ aref [1] es lo mismo que "$ {$ aref} [1]". Si recién está comenzando, es posible que desee
Adopte el hábito de incluir siempre las llaves.
· Esto no copia la matriz subyacente:
$ aref2 = $ aref1;
Obtienes dos referencias a la misma matriz. Si modifica "$ aref1 -> [23]" y luego mira
en "$ aref2 -> [23]" verá el cambio.
Para copiar la matriz, use
$ aref2 = [@ {$ aref1}];
Esto usa la notación "[...]" para crear una nueva matriz anónima, y a $ aref2 se le asigna una
referencia a la nueva matriz. La nueva matriz se inicializa con el contenido de la
matriz referida por $ aref1.
Del mismo modo, para copiar un hash anónimo, puede utilizar
$ href2 = {% {$ href1}};
· Para ver si una variable contiene una referencia, use la función "ref". Devuelve verdadero si
su argumento es una referencia. De hecho, es un poco mejor que eso: vuelve
"HASH" para referencias hash y "ARRAY" para referencias a matrices.
· Si intenta utilizar una referencia como una cadena, obtendrá cadenas como
FORMACIÓN(0x80f5dec) o Hachís(0x826afc0)
Si alguna vez ve una cadena con este aspecto, sabrá que imprimió una referencia
por error.
Un efecto secundario de esta representación es que puede usar "eq" para ver si dos referencias
se refieren a lo mismo. (Pero normalmente debería utilizar "==" en su lugar porque es mucho
más rápido.)
· Puedes usar una cadena como si fuera una referencia. Si usa la cadena "foo" como un
referencia de matriz, se toma como una referencia a la matriz @foo. Esto se llama
suave referencia or simbólico referencia. La declaración "use 'refs' estrictos" inhabilita
esta función, que puede causar todo tipo de problemas si la utiliza por accidente.
Es posible que prefiera utilizar perllol en lugar de perlref; analiza listas de listas y
matrices multidimensionales en detalle. Después de eso, debería pasar a perldsc; es un dato
Libro de recetas de estructura que muestra recetas para usar e imprimir matrices de hashes, hashes
de matrices y otros tipos de datos.
Resum
Todo el mundo necesita estructuras de datos compuestas, y en Perl la forma en que las obtiene es con
referencias. Hay cuatro reglas importantes para administrar referencias: Dos para hacer
referencias y dos por usarlas. Una vez que conozca estas reglas, podrá hacer la mayoría de las
cosas importantes que debe hacer con las referencias.
Créditos
Autor: Mark Jason Dominus, Plover Systems ("[email protected]")
Este artículo apareció originalmente en El sistema Perl Actualidad ( http://www.tpj.com/ ) volumen 3, # 2.
Reproducido con permiso.
El título original era Comprender Referencias Hoy.
Distribuidores Condiciones
Copyright 1998 Perl Diario.
Esta documentación es gratuita; puedes redistribuirlo y / o modificarlo en los mismos términos
como el propio Perl.
Independientemente de su distribución, todos los ejemplos de código de estos archivos se colocan en
el dominio público. Se le permite y se le anima a utilizar este código en sus propios programas.
por diversión o con fines de lucro como mejor le parezca. Un simple comentario en el código que da crédito sería
cortés pero no es obligatorio.
Use perlreftut en línea usando los servicios de onworks.net