Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Cómo y cúando usar subrutinas

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Vie Jun 09, 2006 7:57 pm
MidNight
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Abr 2006
Mensajes: 21
Cómo y cúando usar subrutinas Responder citando

he estado leyendo la mayoria de topicos que hay en el foro, y en estos leia en muchos que recomendaban no usar las subrutinas o procedimientos llamandolos con el prefijo &, pero a decir verdad no encontre el porqué de esta recomendación... en que varia llamar:

&función a funcion() ?

otra duda es, por lo general estoy a acostumbrado a hacer muchas subrutinas, si debo repetir un procedimiento mas de dos veces creo la subrutina de este, entonces si se llama tantas veces a rutinas esto trae algun tipo de efecto negativo? hablando de costos computacionales depronto en programas muy grandes con una cantidad de procesamiento de datos significativa ...

un saludo.
Mensaje Vie Jun 09, 2006 8:09 pm
kidd
Creador de Perl en Español
Creador de Perl en Español
Registrado: 15 Oct 2003
Mensajes: 1389
Ubicación: México
Responder citando

Hola:

La sintaxís correcta efectivamente como dices para realizar llamadas de subrutinas es:
Código:
funcion();


Ahora, realizas una buena práctica, pues realmente el motivo de las subrutinas es evitar reescribir el mismo código una y otra vez, así que si hay algo que vas a ralizar "rutinariamente" en tu script, para ello debes de crear una subrutina, eso es buena práctica de programación.

Más adelante verás que te terminará conviniendo hacer tu propia librería de módulos con aquellas subrutinas que usas una y otra vez en tus scripts, para ello existen. Por ejemplo yo tengo una colección de 3 o 4 módulos que hice y que son indispensables para cuando hago mis scripts pues en ellos tengo subrutinas que acostumbro a usar.

Otra de las ventajas de realizar subrutinas, es que te obliga a encapsular tu código, esto es sumamente importante cuando tienes proyectos grandes en donde puedes de pronto realizar una actualización y donde va a ser necesario por ejemplo, cambiar la manera a la que te conectas a un database. Si en todas tus conexiones usas la misma función, entonces podrás realizar el cambio sin ningún problema, en cambio si repetiste el código una y otra vez, ímaginate el trabajo y la cantidad de errores o bugs que pueden surgir de todos esos cambios.

Mi recomendación es que encapsules siempre que puedas código que vayas a repetir una y otra vez, y si ese mismo código lo vas a usar en varios scripts, entonces haz un módulo, esta sencilla opción es lo que le dá a Perl el poder que tiene.

Un saludo
Mensaje Vie Jun 09, 2006 8:35 pm
MidNight
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Abr 2006
Mensajes: 21
Responder citando

oks, muchas gracias por aportar tu punto de vista, lo comparto tambien intento ser lo más recursivo que pueda en mis scripts y lo de la creación de módulos con las rutinas que se acostumbra utilizar es una excelnte idea, sin embargo aun no queda claro porque es esa la forma correcta para llamar a una subrutina, osea se supone que el operador & se creo para llamarlas... que desventajas presenta llamar a una subrutina de la manera &sub frente a la llamada sub()?

un slaudo.
Mensaje Sab Jun 10, 2006 5:30 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4084
Ubicación: Valladolid, España
Responder citando

Toda la información sobre la subrutinas está (en inglés) en perlsub.

En concreto, la forma de llamar a las subrutinas se puede hacer:
Código:
NOMBRE(LISTA);  # & es opcional con paréntesis.
NOMBRE LISTA;   # Paréntesis son opcionales si ha sido predeclarada/importada.
&NOMBRE(LISTA); # Evita la definición dada por el prototipo.
&NOMBRE;        # Hace el actual valor de @_ visible a la subrutina llamada.


Una subrutina puede ser llamada con un explícito prefijo &. El & es opcional en Perl modernos, así como los paréntesis si la subrutina ha sido predeclarada. El & no es opcional cuando sólo se está nombrando a la subrutina, como cuando se usa como un argumento a defined() y undef(). Ni tampoco cuando quieres hacer una llamada indirecta con el nombre de una subrutina o referencia usando las formas &$subref() o &{$subref}(), aunque la notación $subref->() soluciona el problema. Ver perlref para más información sobre todo esto.

Veamos un ejemplo. Esta es la clásica solución de colocar primero el núcleo del programa y luego las subrutinas:
Código:
    1 #!/usr/bin/perl -l
    2 use warnings;
    3 use strict;
    4
    5 ### Constantes
    6 my $k = 4;
    7
    8 ### Programa ###
    9 for(my $i=1; $i<=10; $i++) {
   10     print $i, " -> ", multiplica( $i );
   11 }
   12
   13 ### subrutinas ###
   14 sub multiplica {
   15     my $arg = $_[0];
   16     return $arg * $k;
   17 }
(es un programa muy simple que saca la tabla de multiplicar de un valor $k)
En caso de tener un Perl antiguo, estariamos obligados a poner &multiplica($i) en la línea 10 porque la definición de la subrutina ocurre al final del código. En un Perl moderno, ya no es necesario, como en el ejemplo. En el caso contrario, en el de poner primero las subrutinas y luego el núcleo del programa, el poner el & sería opcional en cualquier Perl.

Ahora con prototipos. Vamos a declarar cómo van a ser las subrutinas antes de usarlas:
Código:
    1 #!/usr/bin/perl -l
    2 use warnings;
    3
    4 sub mul($);
    5
    6 my $k = 4;
    7
    8 for(my $i=1; $i<=10; $i++) {
    9     print $i, " -> ", mul $i, " ", $i+3;
   10 }
   11
   12 sub mul ($) {
   13     my $arg = $_[0];
   14     return $arg * $k;
   15 }
En la línea 4 declaramos que en nuestro programa existe una función llamada mul que admite un argumento escalar ($). La definición de la función está al final. Ves que en la lína 12 nos vemos obligados a poner los paréntesis con el prototipo. Perl busca una función tal cual la hemos declarado antes.
Y al llegar a la hora de usarla, en la línea 9, vemos que, opcionalmente, hemos podido quitar el & y los paréntesis. Al principio pensamos que Perl se puede liar cuando quitamos los paréntesis, ya que vemos que después de mul $i sigue una coma y más elementos que podrían parecer más argumentos a la función mul (un espacio en blanco y la expresión $i+3), pero gracias a la declaración de la línea 4, Perl ya sabe que mul sólo tiene un argumento, el primer $i.
Los prototipos sirven para la comprobación de los argumentos pasados a las subrutinas, en tiempo de compilación. Es una forma de obligarnos a nosotros mismos o a los usuarios de nuestras funciones a colocar de forma exacta los argumentos que esas subrutinas esperan.

Y finalmente, en el caso de poner primero las subrutinas antes del núcleo del programa, podemos ahorrarnos las declaraciones, prototipos, el & y los paréntesis.

La recomendación actual es usar los prototipos sólo para las nuevas funciones en los nuevos módulos que estemos construyendo, y no retocar las funciones de los módulos que ya hemos publicado. Pueden dar problemas a las personas que ya lo están usando.

Un ejemplo. Supongamos que tenemos este programa:
Código:
#!/usr/bin/perl -lw
sub func {
    my $n = shift;
    print "Me has pasado un $n";
}

@foo = ("Hola");
func(@foo);
Tenemos una función sin prototipos. Al ejecutarlo, @foo, una lista, se manda a la función y ésta coge el primer valor y lo saca en pantalla, por lo que la salida del programa es: Me has pasado un Hola. Pero, si cambiamos la línea sub func { por otra con el prototipo sub func ($) { indicando que sólo queremos un valor escalar, al llegar a la línea de llamar a la función func, @foo es interpretado en contexto escalar (eso es lo que espera func) por lo que entonces obtenemos el número de elementos que hay en @foo. La salida es ahora: Me has pasado un 1.
Mensaje Sab Jun 10, 2006 7:30 am
MidNight
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Abr 2006
Mensajes: 21
Responder citando

Hola explorer, ha sido una excelente explicación respecto a la duda que escribí, te agradezco que te hallas tomado el tiempo de responder, y me ha quedado claro, leeré los documentos que me recomiendas para profundizar en el tema, claro está si alguien desea aportar su punto de vista bienvenido es..

un slaudo.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group