Perl para los nuevos en Perl
Lo que sigue es la versión libre en español del artículo "Perl for Newbies" (parte 1) escrita por Shlomi Fish y que se puede leer en su versión original en la url http://perl-begin.org/tutorials/perl-for-newbies/
Introducción
"Hay más de una manera de hacerlo." (El lema de Perl)
Las capacidades de Perl
Strings y estructuras de datos que son de tamaño ilimitado, anidadas a cualquier profundidad.
Sintaxis potente y funciones incorporadas.
Soporte extendido e integrado de expresiones regulares.
Soporte para los espacios de nombres, clases y objetos.
Capacidades de programación funcional, tales como cierres y continuaciones.
CPAN - un archivo completo y en línea de módulos reutilizables y de fácil instalación.
Poderoso depurador con front-ends visuales opcionales.
Funciona en casi cualquier plataforma imaginable.
Código relativamente portable y seguro.
Una breve historia de Perl
Perl fue introducido en 1987 (4 años antes de Linux mismo) cuando el autor, Larry Wall, lanzó la versión 1.000. La razón de su creación fue que Wall estaba descontento con la funcionalidad que sed, C, awk y la Bourne Shell le ofrecian. Buscó un lenguaje que combinara todas sus mejores características y que tuviera el menor número de inconvenientes propios.
Desde entonces Perl ha visto varias versiones, cada una añadiendo funcionalidades adicionales. Perl 5, lanzado en 1994, fue una completa re-escritura del intérprete Perl e introdujo elementos tales como referencias duras, módulos, objetos y ámbito léxico.
Perl se hizo especialmente popular como un lenguaje para escribir scripts del lado del servidor para la Web. Pero ese no es el único uso de Perl ya que es de uso común para las tareas de administración del sistema, gestión de bases de datos, así como la escritura de aplicaciones GUI.
El ciclo de desarrollo con Perl
Perl es interpretado, por lo que no se necesita ninguna compilación. Para usar Perl se debe crear un archivo de texto que contiene el programa. Este archivo se puede escribir con cualquier editor de texto. Se recomienda que los nombres de los scripts de Perl terminen con ".pl" para identificarlos como scripts de Perl.
Una vez hecho, se invoca el intérprete de Perl con el nombre del archivo creado. Asumiendo que tu archivo se llama "myscript.pl", debes escribir:
$ perl myscript.pl
en la línea de comandos (y pulsar Enter). Si el programa contiene errores o advertencias se mostrarán. Si el programa no contiene errores, se ejecuta.
El hecho de que el programa se ejecute no significa que hace lo que quieres que haga. Vamos a aprender cómo depurar programas en Perl, más adelante en esta serie.
Comandos de salida básicos (el script "Hola Mundo")
En Perl usamos el comando print para mostrar cadenas y expresiones en la pantalla.
El neófito script "Hola Mundo!" puede ser escrito en Perl de la siguiente manera:
print "Hola, mundo \n";
Ahora lo explicamos:
La cadena está encerrada entre comillas dobles ("...") porque así es como se representan las constantes de cadena en Perl.
\n es un carácter especial que se llama "salto de línea". Cuando se imprime una nueva línea, verás que la salida comienza en una nueva línea.
El punto y coma (;) al final indica que este es el final de una sentencia de Perl. Cada sentencia Perl debe terminar con un punto y coma.
Más sobre punto y comas
Un programa de Perl puede incluir, por supuesto, más de una sentencia. Para ello es necesario colocar un punto y coma al final de cada sentencia o sino el intérprete se verá confundido.
No es suficiente para poner a cada sentencia en una línea aparte, pues de hecho ni siquiera es necesario. Los dos programas siguientes son equivalentes:
print "One Fish, \n"; print "Two Fish, \n"; print "Red Fish, \n"; print "Blue Fish. \n";
y
print "One Fish, \n"; print "Two Fish, \n"; print "Red Fish, \n"; print "Blue Fish. \n";
Sin embargo, para facilitar la lectura y fácil depuración, se recomienda que cada sentencia se encuentre en una línea separada. Y a veces es útil dejar más de una línea en blanco entre ellas.
Expresiones
Perl soporta casi todos los operadores matemáticos como +, -, *, / y paréntesis ((...)). Un ejemplo vale más que mil palabras:
print "5 + 6 =", 5 + 6, "\n"; print "(2 + 3) * 6 =", (2 + 3) * 6, "\n"; print "2 + 3 * 6 =", 2 + 3 * 6, "\n"; print "2 elevado a la potencia de 8 es", 2 ** 8, "\n"; print "10-5 =", 10-5, ". 5-10=", 5-10, "\n"; print "2/3 =", 2/3, "\n";
La salida de este programa es:
5 + 6 = 11 (2 + 3) * 6 = 30 2 + 3 * 6 = 20 2 elevado a la potencia de 8 es 256 10-5 = 5. 5-10 = -5 2/3 = 0,666666666666667
Los operadores tienen la misma precedencia que sus equivalentes matemáticos. Los paréntesis son útiles para asegurarse de una sub-expresión se evaluará antes que todas los demás.
Nota:
Puedes usar comas para imprimir más de una expresión a la vez. Es mejor que escribir un comando print diferente para cada expresión. Sin embargo, para facilitar la lectura, se recomienda separar las expresiones en varios print.
Operadores y precedencia
He aquí algunos operadores Perl de interés:
+, -, *, /
Respectivamente suma, resta, multiplicación y división de números de punto flotante.
a ** b
Eleva "a" a la potencia de "b". Trabaja con números de punto flotante también.
a . b
Concatena dos cadenas. La coma (,) como se usó en el print en realidad no concatena dos cadenas sino que imprime una después de la otra. Hay una sutil diferencia en la funcionalidad del comando print también, pero no vamos a entrar en eso ahora.
print "Hola" . " " . "Mundo!" . "\n" . "Y esta es la segunda línea. \n";
a % b
Devuelve el módulo (resto) de "a" dividido "b". Si "a" y "b" no son números enteros se redondean a un valor entero.
(Sub-expresión)
Con paréntesis se asegura que la sub-expresión se evalúa separada de la expresión entera, esto podría anular la precedencia de operadores predeterminada.
print "2 + 10 - 5*2 =", 2+10-5*2, "\n"; print "2 + (10-5) * 2 =", 2+(10-5)*2, "\n";
La salida de este programa es:
2 + 10 - 5*2 = 2 2 + (10-5) * 2 = 12
Hay muchos más, pero serán cubiertos más adelante. Para obtener una lista completa e información más detallada acerca de los distintos operadores de Perl consulte el documento "perlop" en el sistema.
Funciones
¿Cuántos caracteres hay en el lema de Perl? Perl puede decir eso de inmediato:
print length("Hay más de una manera de hacerlo."), "\n";
length()
es una función incorporada que indica la cantidad de caracteres de una cadena. Una función es una subrutina llamada que acepta varios argumentos y devuelve un valor que puede ser luego evaluado como parte de una expresión mayor, o utilizarse directamente.Para ayudarnos a entender más las funciones vamos a inspeccionar la función
substr
de Perl (abreviatura de "sub-string"). substr devuelve un substring de una cadena dada. El primer argumento es una cadena, el segundo es el desplazamiento desde donde tomar el substring y el tercero es la longitud del substring a tomar. El tercero es opcional y si no se especifica devuelve el substring hasta el final de la cadena.Un ejemplo lo ilustrará mejor:
print substr("Una larga cadena", 3), "\n"; print substr("Una larga cadena", 1, 4), "\n"; print substr("Una larga cadena", 0, 9), "\n";
La salida de este programa es:
larga cadena na l Una larga
Notarás que la posición del primer carácter es 0.
Las comas se utilizan para separar los argumentos de la función y son obligatorias en Perl. Sin embargo el paréntesis que encierra los argumentos es opcional. El programa anterior podría haberse escrito como:
print ((substr "Una larga cadena", 3), "\n"); print ((substr "Una larga cadena", 1, 4), "\n"); print ((substr "Una larga cadena", 0, 9), "\n");
Necesitamos un conjunto adicional de paréntesis para que
print
(el cual también es una función) no se confunda y considere el resultado de la operación substr como su único argumento, ignorando "\n". Si no tiene sentido no te preocupes, sin embargo recuerda que un conjunto de paréntesis que envuelve a la lista de argumentos de una función no puede hacerte daño.Fijate la salida de este programa:
print ((substr "largo",2),"\n"); print (substr "largo",2),"\n"; print substr( "largo",2),"\n";
La función int()
Otra función útil es
int()
. Esta función toma un número y lo redondea hacia abajo al número entero más cercano. He aquí un ejemplo:print "La parte entera de 5.67 es ", int(5.67), "\n";
Más sobre strings
En Perl las cadenas y los números se convierten a la perfección entre sí en función del contexto en el que se utilizan.
print (("5" + "6"), "\n"); print ((56 . 23), "\n");
La salida de este programa es:
11 5623
Secuencias de escape
Ya hemos encontrado la "secuencia de escape" \n que puede venir dentro de las cadenas y designa un carácter de nueva línea. Hay muchos otros en Perl. Aquí está una lista de las más importantes:
\\ - Designa una real barra invertida (\)
\"- Designa un carácter real de comillas dobles (")
\$ - Un signo real de pesos (un verdadero $ hace algo más)
\@ - Un verdadero signo de arroba (@ sin escapar hace algo más)
\n - un carácter de nueva línea
\r - una señal de retorno de carro
\t - un carácter de tabulación
\xDD - donde "DD" son dos dígitos hexadecimales - devuelve el carácter cuyo código ASCII es "DD".
He aquí un ejemplo para ilustrar algunas de ellas:
print "Me dije \"hola!\" a mí mismo, y no recibí respuesta. \n"; print "Este programa le costará \$100 en efectivo. \n"; print "La guerra KDE\\GNOME hace que la vida en el mundo de Linux sea" . " más interesante. \n";
cuya salida es:
Me dije: "¡hola!" a mí mismo, y no recibí respuesta. Este programa le costará $100 en efectivo. La guerra KDE\GNOME hace que la vida en el mundo de Linux sea más interesante.
Variables
Las variables son celdas con nombres almacenadas en la memoria del ordenador que pueden contener cualquier valor simple. Se puede cambiar el valor de una variable y más tarde se puede recuperar el último valor asignado tantas veces se como quisiera.
Las variables en Perl comienzan con un signo pesos ($) y le sigue cualquier número de letras, dígitos y guión-bajos (_), siempre y cuando la primera letra después del signo pesos sea una letra o un guión-bajo.
Para recuperar el valor de una variable, simplemente coloca el nombre de la variable (de nuevo con el signo pesos) dentro de una expresión.
Para asignar un valor a una variable, uno coloca el nombre de la variable completa (con el signo pesos) delante de un signo igual (=) y coloca el valor a la derecha del signo igual. Esta forma se considera una declaración y debe ser seguido por un punto y coma. El valor asignado puede ser una expresión que puede contener otras variables (incluyendo la propia variable asignada!).
Un ejemplo lo ilustrará:
$myvar = 17; $x = 2; print $myvar, " * ", $x, "=", ($myvar * $x), "\n"; $x = 10; print $myvar, " * ", $x, "=", ($myvar * $x), "\n"; $x = 75; print $myvar, " * ", $x, "=", ($myvar * $x), "\n"; $x= 24; print $myvar, " * ", $x, "=", ($myvar * $x), "\n";
La salida de este programa es:
17 * 2 = 34 17 * 10 = 170 17 * 75 = 1275 17 * 24 = 408
Hay varias cosas que se pueden notar:
El valor de $x cambia a lo largo del programa. No hay ningún problema y ??por lo general es necesario modificar el valor de una variable.
Mediante el uso de $myvar podemos asegurar que en el caso de desear cambiar su valor, sólo tenemos que cambiarlo en un solo lugar, no en todos los lugares donde parece.
"+=" y sus amigos
Perl proporciona un atajo para escribir "$myvar = $myvar + $value", o "$myvar = $myvar / $value" y operaciones similares. He aquí un ejemplo:
$x = 1; $y = 0; print "2^", $y, "=", $x, "\n"; $x *= 2, $y += 1; print "2^", $y, "=", $x, "\n"; $x *= 2, $y += 1; print "2^", $y, "=", $x, "\n"; $x *= 2, $y += 1; print "2^", $y, "=", $x, "\n"; $x *= 2, $y += 1; print "2^", $y, "=", $x, "\n"; $x *= 2, $y += 1; print "2^", $y, "=", $x, "\n";
Dado que las operaciones de $x += 1 y $x -= 1 son comúnmente utilizadas, también fueron asignadas a un operador independiente. Uno puede usar $x++ y $x-- para realizarlas. Por ejemplo, el programa anterior se podría haber escrito como:
$x = 1; $y = 0; print "2^", $y, "=", $x, "\n"; $x *= 2, $y++; print "2^", $y, "=", $x, "\n"; $x *= 2, $y++; print "2^", $y, "=", $x, "\n"; $x *= 2, $y++; print "2^", $y, "=", $x, "\n"; $x *= 2, $y++; print "2^", $y, "=", $x, "\n"; $x *= 2, $y++; print "2^", $y, "=", $x, "\n";
Entrada
Para recibir un valor por parte del usuario Perl proporciona el operador <>. Cuando aprieta Enter, este operador lee una línea desde la línea de comandos, y la devuelve (junto con el carácter de nueva línea).
He aquí un ejemplo:
print "Introduzca su nombre: \n"; $nombre = <>; chomp($nombre); print "Hola ", $nombre, "!\n";
Observe la función
chomp()
que elimina el carácter de nueva línea al final de la variable. Usted querrá usarlo al obtener la entrada del usuario.He aquí otro ejemplo:
print "Introduzca una cadena:"; $cadena = <>; chomp ($cadena); print "La cadena que escribió contiene ", length($cadena), " caracteres. \n";
El bucle for
El bucle
for
nos permite iterar sobre una secuencia de números y repetir el mismo conjunto de operaciones para cada número.Por ejemplo el siguiente programa imprime todos los números del 1 al 100:
for $i (1 .. 100) { print $i, "\n"; }
Algunas explicaciones sobre la sintaxis:
$i es la variable de iteración. Recibe el valor 1, luego el valor 2, a continuación 3 y así sucesivamente hasta que es igual a 100, después de eso el bucle termina.
Las llaves ({...}) encapsulan el bloque del bucle. El bloque del bucle se ejecuta una vez para cada valor de $i. Dentro del bloque, llamado cuerpo del bucle, se puede utilizar $i y obtener su valor actual.
Podemos anidar bucles, por ejemplo el siguiente programa imprime la tabla de multiplicar:
for $y (1 .. 10) { for $x (1 .. 10) { $product = $y * $x; # Agregar tantos espacios en blanco como sea necesario # para que el número ocupe exactamente 4 caracteres. for $whitespace (1 .. (4 - length($product))) { print " "; } print $product; } # Mover a la siguiente línea print "\n"; }
Usted puede haber notado los comentarios del programa. En Perl los comentarios comienzan con el signo numeral (#) y se extienden hasta el final de la línea. Escribir las tablas de multiplicar con las etiquetas que indican los números que se multiplican se deja como ejercicio para el lector.
Condicionales
Los condicionales nos permiten ejecutar un grupo de instrucciones si una determinada condición se cumple. Por ejemplo el siguiente programa informa al usuario si su nombre comienza con la letra "A":
print "Introduzca su nombre: \n"; $nombre = <>; if (substr($nombre, 0, 1) eq "A") { print "Su nombre comienza con 'A' \n"; } else { print "Su nombre no comienza con 'A' \n"; }
El código substr($nombre, 0,1) eq "A" es una expresión de la condición que utiliza el operador eq de Perl, que devuelve verdadero si y sólo si las cadenas son iguales. Hay más de estos operadores y se explicarán en breve.
En el interior de los corchetes después del if está el código a ser ejecutado por el condicional. Ese código puede ser tan largo como quieras. La parte else se ejecuta cuando el condicional es falso, y es opcional.
Operadores de comparación numéricos
Perl proporciona al usuario 6 operadores de comparación numéricos. Ellos son:
$x == $y $x e $y son iguales.
$x > $y $x es mayor que $y
$x < $y $x es menor que $y
$x >= $y $x es mayor o igual que $y
$x <= $y $x es menor o igual que $y
$x != $y $x es distinto que $y
Los operadores pueden utilizarse dentro de los condicionales y también afuera, como parte de una expresión normal. El siguiente programa imprime todos los números entre 1 y 100 que no son divisibles por 3:
for $n (1 .. 100) { if (($n% 3) != 0) { print $n, "\n"; } }
Operadores de comparación de cadenas
Con el fin de comparar cadenas por igualdad o por orden alfabético, podemos utilizar los seis operadores de comparación de cadenas. Ellos son:
$x eq $y $x e $y son iguales.
$x gt $y $x es mayor alfabéticamente que $y
$x lt $y $x es menor alfabéticamente que $y
$x ge $y $x es mayor alfabéticamente o igual que $y
$x le $y $x es menor alfabéticamente o igual que $y
$x ne $y $x es distinto que $y
Tener en cuenta que los operadores de cadena se construyen a partir de las iniciales de sus nombres abreviados. Por ejemplo: eq = igual; gt = mayor que. La comparación de cadenas en Perl distingue entre mayúsculas y minúsculas, si quieres un caso de comparación de cadenas insensible, utiliza la función
lc
para convertir las cadenas a minúsculas antes de la comparación.Ejemplo:
print "Introduzca su nombre de pila: \n"; $nombre = <>; chomp ($nombre); if (lc($nombre) eq "rachel") { print "Su nombre es Rachel \n"; } else { print "Su nombre no es Rachel \n"; }
Nota: La función
lc()
convierte una cadena a minúsculas.Operadores booleanos
A veces es útil comprobar la validación de más de una condición. Para hacer esto Perl suministra los operadores booleanos.
&&
$x && $y es verdadera si tanto $x e $y son verdaderas. Se le llama el "and lógico" de los dos operandos $x e $y.
||
$x || $y (llamado el "or lógico" de $ $x e $y) es verdadera si uno o ambos de sus operandos es verdadero.
!
!$x (que se pronuncia "not $x") devuelve verdadero si $x es falso.
Tenga en cuenta que si se evalúa el primer operando como falso en una operación &&, el segundo operando no se evalúa en absoluto. Del mismo modo, si el primer operando de || resultó ser verdadero, el segundo no será evaluado tampoco.
Si desea que ambos operandos sean evaluados en cualquier caso se necesita asignarlos a una variable primero.
He aquí algunos ejemplos:
print "Introduce el límite inferior del rango: \n"; $inferior = <>; chomp($inferior); print "Introduce el límite superior del rango: \n"; $superior = <>; chomp($superior); if ($inferior > $superior) { print "Esto no es un rango válido \n"; } else { print "Introduce un número: \n"; $numero = <>; chomp($numero); if ($inferior <= $numero) && ($numero <= $superior)) { print "El número se encuentra en el rango! \n"; } else { print "El número no está en el rango! \n"; } }
print "Introduzca su nombre: \n"; $nombre = <>; chomp($nombre); $prim_letra = lc(substr($name, 0, 1)); if (($prim_letra eq "a") || ($prim_letra eq "b") || ($prim_letra eq "c")) { print "Su nombre comienza con una de las " . " tres primeras letras del abecedario. \n"; } else { print "Su nombre no comienza con una de las " . "primeras tres letras del abecedario. \n"; }
Expresiones verdaderas vs Expresiones falsas
En Perl toda expresión se considera verdadera a excepción de los tres casos siguientes:
El número 0.
La cadena vacía ("").
Un valor especial llamado undef. Este es el valor por defecto de todas las variables que no han sido inicializadas antes de su uso.
Una de las maneras más convenientes de cancelar una porción de código es de envolverlo en un bloque if (0) {... }. Por lo general es más rápido que agregar el símbolo de comentario al principio de cada línea. Por supuesto no debes distribuir el código de esa manera, pero es útil para testear prototipos.
Estructura elsif
La sintaxis completa de la instrucción if es la siguiente:
if ($condition0) { } elsif ($condition1) { } elsif ($condition2) { } . . . else { }
Se ejecutará el enésimo bloque elsif solo si no se cumplen todas las condiciones establecidas en los bloques anteriores y si se cumple su condición.
Se puede hacer lo mismo anidando varios if dentro de bloques else, pero es agradable que Perl nos ahorre tantas llaves y tabulaciones con la instrucción elsif.
El bucle while
El bucle
while
nos permite repetir una secuencia de sentencias un número arbitrario de veces durante todo el tiempo que se cumple una condición. La sintaxis es muy similar a la sentencia if y se introducirá en el siguiente ejemplo:print "Introduce un número: \n"; $numero = <>; chomp($numero); $potencia_de_2 = 1; while ($potencia_de_2 < $numero) { $potencia_de_2 *= 2; } print ("La primer potencia de 2 que es " . "mayor a tu número es ", $potencia_de_2, "\n");
Es posible que el bloque del bucle
while
no se ejecute en absoluto, si la condición no se cumple en el inicio.El siguiente script revisa si una cadena determinada se compone únicamente de caracteres "a":
print "Introduce una cadena: \n"; $cadena = <>; chomp($cadena); # Inicializa todas_a a TRUE $todas_a = 1; # La primera posición en la cadena. $posicion = 0; while ($todas_a && ($posición < length($cadena))) { $char = lc(substr($cadena, $posición, 1)); if ($char ne "a") { $todas_a = 0; } # Incrementar la posición $posicion++; } if ($todas_a) { print "La cadena introducida tiene solo letras A! \n"; } else { print "Al menos uno de los caracteres de la cadena " . "introducida no es \"A\". \n"; }
Comandos last y next
Dentro de los bucles
for
y while
se puede utilizar dos comandos especiales, llamados last y next. Para terminar un bucle prematuramente se usa last, mientras que next saltea el resto del cuerpo del bucle y vuelve a la condición para verificar si se cumple y entonces ejecuta el bucle de nuevo.De forma predeterminada last y next operan en el bucle más interno. Sin embargo el bucle al que se refieren puede ser controlado por una etiqueta en el bucle y especificando esta etiqueta como un parámetro de last o next.
El siguiente ejemplo es una nueva versión del script "Todas A" con last:
print "Introduce una cadena: \n"; $cadena = <>; chomp($cadena); # La primera posición en la cadena. $posicion = 0; while ($posicion < length($cadena)) { $char = lc(substr($cadena, $posición, 1)); if ($char ne "a") { last; } # Incrementar la posición $posicion++; } # Si la posición es igual al final de la cadena significa que el bucle no # fue terminado prematuramente, por lo que una "a" no fue encontrada. if ($posicion == length($cadena)) { print "La cadena introducida tiene solo letras A! \n"; } más { print "Al menos uno de los caracteres de la cadena " . "introducida no es \"A\". \n"; }
Este programa imprime una pirámide inclinada hacia la izquierda:
print "Introduce la longitud de la pirámide: \n"; $size = <>; chomp($size); ROW_LOOP: for $row (1 .. $size) { for $col (1 .. ($size + 1)) { if ($col > $row) { print "\n"; next ROW_LOOP; } print "#"; } }
"ROW_LOOP" es la etiqueta para el bucle externo y se puede ver que next la utiliza como un parámetro. Con todo, next y last a veces son muy convenientes (pero no se lo digas a Edsger W. Dijkstra!), así que lo verás a menudo en el código.
Arrays
Los arrays son una sucesión de variables cuyos miembros pueden ser recuperados y asignados usando índices. Un índice pasado a un array podría ser, y usualmente lo es, otra variable.
Para referirse al i-ésimo elemento de un array @myarray, uno utiliza la sintaxis
$myarray[$i]
. Este elemento puede ser asignado a otro o su valor puede ser recuperado, con la misma notación.Los índices de los arrays son números enteros y el primer índice es 0. Al igual que con la longitud de cadenas, el número de elementos de un array está limitado sólo por la cantidad de memoria disponible en el equipo. También se lo llama arreglo o vector.
El siguiente programa imprime los números primos hasta el 200:
$num_primos = 0; # Ponemos 2 como el primer primo, así que no vamos a tener un array vacío, # Lo que podría confundir al intérprete de Perl $primos[$num_primos] = 2; $num_primos++; MAIN_LOOP: for $number_to_check (3 .. 200) { for $p (0 .. ($num_primos - 1)) { if ($number_to_check % $primos[$p] == 0) { next MAIN_LOOP; } } # Si llegamos a este punto significa que $number_to_check no es # Divisible por ningún número primo que vino antes. $primos[$num_primos] = $number_to_check; $num_primos++; } for $p (0 .. ($num_primos - 1)) { print $primos[$p], ","; } print "\n";
La notación
scalar(@miarray)
puede ser usada para referirse al número de elementos de una matriz. Este número es igual al máximo índice que se asigna en la matriz más uno. También verá la notación $#myarray que es igual al propio índice máximo (o -1 si el array está vacío).Así, por ejemplo, el programa anterior podría haber sido escrito como sigue:
# Ponemos 2 como el primer primo, así que no vamos a tener un array vacío, # Lo que podría confundir al intérprete de Perl $primos[0] = 2; MAIN_LOOP: for $number_to_check (3 .. 200) { for $p (0 .. $#primos) { if ($number_to_check % $primos[$p] == 0) { next MAIN_LOOP; } } # Si llegamos a este punto significa que $number_to_check no es # Divisible por ningún número primo que vino antes. $primos[scalar(@primos)] = $number_to_check; } for $p (0 .. $#primos) { print $primos[$p], ","; } print "\n";
El operador ','
En Perl la coma (,) es un operador, que nos encontramos antes en las llamadas a funciones. La coma concatena dos arrays. Podemos utilizarlo para inicializar un array en una llamada:
@lines = ("Un pez", "Dos peces", "pez rojo", "pescado azul"); for $idx (0 .. $#lines) { print $lines[$idx], "\n"; }
También podemos utilizarlo para concatenar dos arrays existentes:
@primes1 = (2, 3, 5); @primes2 = (7, 11, 13); @primos = (@primes1, @primes2, 17); @primos = (@primos, 19); for $idx (0 .. $#primos) { print $primos[$idx], "\n"; }
¿Por qué se utiliza en las llamadas a funciones? En Perl cada función acepta un array de argumentos y devuelve un array de valores. Es por eso que la coma es útil para llamar a funciones que aceptan más de un argumento.
Índices negativos
La expresión
$myarray[-$n]
es equivalente a $myarray[scalar(@myarray) - $n]
. Es decir: los subíndices con índices negativos devuelven el n-ésimo elemento desde el final del array. Así que para obtener el valor del último elemento se puede escribir $myarray[-1] y para el penúltimo $myarray[-2], etcTenga en cuenta que también hay que asegurarse de que los subíndices del array que son continuamente decrementados no provoquen desbordamiento por debajo de 0, sino comenzará a recibir los elementos desde el final del array.
El bucle foreach
Utilizando el bucle
foreach
podemos iterar sobre todos los elementos de un array y realizar el mismo conjunto de operaciones en cada uno de ellos. He aquí un ejemplo:@numbers = (15,5,7,3,9,1,20,13,9,8,15,16,2,6,12,90); $max = $numbers[0]; $min = $numbers[0]; foreach $i (@numbers[1..$#numbers]) { if ($i > $max) { $max = $i; } elsif ($i < $min) { $min = $i; } } print "The maximum is " . $max . "\n"; print "The minimum is " . $min . "\n";
El bucle
foreach
en el ejemplo asigna cada uno de los elementos del array a la variable $ i, uno a la vez, y ejecuta el mismo conjunto de comandos para cada valor.La palabra for y el operador ..
La palabra clave for en Perl significa exactamente lo mismo que foreach y se puede utilizar cualquiera de ellas indistintamente.
$x .. $y es un operador especial que devuelve un array que contiene la secuencia de números enteros consecutivos desde $x hasta e inclusive $y. Ahora uno puede entender completamente la construcción for $i (1 .. 10) que se utilizó en el comienzo de esta lectura.
Funciones incorporadas de arrays
push
La función
push
agrega un elemento al final de un array. La sintaxis es push @array_to_append_to, @array_to_append
o push @array, $elem1
. Por ejemplo, el programa de números primos anterior se puede escribir como:# Ponga 2 como el primer primo, así que no vamos a tener el array vacío @primos = (2); MAIN_LOOP: for $number_to_check (3 .. 200) { foreach $p (@primos) { if ($number_to_check % $p == 0) { next MAIN_LOOP; } } # Si llegamos a este punto significa $number_to_check no es # Divisible por ningún número primo que vino antes. push @primos, $number_to_check; } foreach $p (@primos) { print $p ", "; } print "\n";
Observe que push es equivalente a escribir @array = (@array, $extra_elem), pero se recomienda utilizarlo, ya que minimiza la posibilidad de error y se ejecuta más rápido.
pop
La función
pop
extrae el último elemento de un array y lo devuelve. He aquí un pequeño ejemplo para demostrarlo:# Este programa imprime los números del 10 al 1. @numbers = (1 .. 10); while (scalar(@numbers)> 0) { $i = pop(@numbers); print $i, "\n"; }
shift
La función
shift
extrae el primer elemento de un array y lo devuelve. El array cambiará para contener sólo los elementos que estaban presentes allí anteriormente con los índices 1 hasta scalar(@array) -1.Aquí está el ejemplo anterior, pero usando shift en vez de pop:
# Este programa imprime los números del 1 al 10. @numbers = (1 .. 10); while (scalar(@numbers)> 0) { $i = shift(@numbers); print $i, "\n"; }
join
La sintaxis es
join($separador, @array)
y lo que hace es concatenar los elementos de @array en una cadena separados por $separador. He aquí un ejemplo:@myarray = ("Un pez", "Dos peces", "Pez rojo", "Pez azul"); print join("\n", @myarray), "\n";
reverse
La función
reverse
devuelve un array conteniendo los elementos del array que se le pasa como argumento pero en reversa. He aquí un ejemplo:print "Introduce algunas líneas: \n"; $line = <>; chomp($line); while($line) { push @mylines, $line; $line = <>; chomp($line); } print "Sus líneas en reversa son: \n", join("\n", reverse(@mylines)), "\n";
Note que tipeando
scalar(reverse($escalar))
se obtiene la cadena que contiene los caracteres de $escalar a la inversa. En cambio scalar(reverse(@array))
concatena el array en una cadena y luego invierte sus caracteres.@rima = ('pocas', 'olas', 'mar'); print join(' ',reverse(@rima)); print "\n"; print scalar(reverse(@rima)); print "\n";
Su salida es:
mar olas pocas ramsalosacop
El operador x
La expresión
(@array) x $num_veces
devuelve un array que se compone de $num_veces copias de @array, uno tras otro. La expresión $escalar x $num_veces
, por el contrario, devuelve $num_veces copias de $escalar concatenadas en una cadena.Por eso es importante si el operando de la izquierda está entre paréntesis o no. Es una buena idea asignar el operando de la izquierda a una variable antes de usar el operador x para tener la expresión final lista.
He aquí un ejemplo para ilustrar el uso:
print "Prueba 1: \n"; @myarray = ("Hola", "Mundo"); @array2 = ((@myarray) x 5); print join (",", @array2), "\n \n"; print "Prueba 2: \n"; @array3 = (@myarray x 5); print join (",", @array3), "\n \n"; print "Prueba 3: \n"; $cadena = "oncatenac"; print (($cadena x 6), "\n \n"); print "Prueba 4: \n"; print join ("\n", (("hola") x 5)), "\n \n"; print "Prueba 5: \n"; print join ("\n", ("hola" x 5)), "\n \n";
¿Puedes adivinar cuál será el resultado de este programa?
Aquí hay una muestra:
Prueba 1: Hola,Mundo,Hola,Mundo,Hola,Mundo,Hola,Mundo,Hola,Mundo Prueba 2: 22222 Prueba 3: oncatenaconcatenaconcatenaconcatenaconcatenaconcatenac Prueba 4: hola hola hola hola hola Prueba 5: holaholaholaholahola
No hay comentarios:
Publicar un comentario