• Publicidad

Cómo y cúando usar subrutinas

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Cómo y cúando usar subrutinas

Notapor MidNight » 2006-06-09 20:57 @914

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.
Imagen
Avatar de Usuario
MidNight
Perlero nuevo
Perlero nuevo
 
Mensajes: 21
Registrado: 2006-04-29 13:31 @604

Publicidad

Notapor kidd » 2006-06-09 21:09 @923

Hola:

La sintaxís correcta efectivamente como dices para realizar llamadas de subrutinas es:
Código: Seleccionar todo
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
Uriel Lizama Perl programmer fundador de Perl en Español
Perl Programming Language
Avatar de Usuario
kidd
Creador de Perl en Español
Creador de Perl en Español
 
Mensajes: 1166
Registrado: 2003-10-15 16:52 @744
Ubicación: México

Notapor MidNight » 2006-06-09 21:35 @941

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.
Imagen
Avatar de Usuario
MidNight
Perlero nuevo
Perlero nuevo
 
Mensajes: 21
Registrado: 2006-04-29 13:31 @604

Notapor explorer » 2006-06-10 06:30 @312

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: Seleccionar todo
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: Seleccionar todo
    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: Seleccionar todo
    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: Seleccionar todo
#!/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.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor MidNight » 2006-06-10 08:30 @396

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.
Imagen
Avatar de Usuario
MidNight
Perlero nuevo
Perlero nuevo
 
Mensajes: 21
Registrado: 2006-04-29 13:31 @604


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados