Lección 7
Subrutinas

Las subrutinas son secuencias de instrucciones que se invocan desde un programa para ejecutar una tarea. Una vez completadas regresan el control al lugar de donde fueron llamadas y pueden ser definidas por el programador o proporcionadas por el lenguaje de programación. La diferencia principal entre una función y un procedimiento es que las funciones regresan un valor como resultado de su ejecución mientras que los procedimientos no lo hacen. Ambos se componen de un cuerpo donde se encuentran las instrucciones que se ejecutarán y de una cabecera donde se especifica su nombre, sus parámetros y su tipo de retorno (si se trata de una función). Su propósito principal es encapsular secciones de código que se puede utilizar múltiples veces, reduciendo el tamaño de los programas, mejorando su legibilidad y facilitando su mantenimiento.[1] A la cabecera de las subrutinas así como a su cuerpo se les llama «declaración» mientras que la instrucción en el programa principal usada para iniciar su ejecución recibe el nombre de «invocación».

Declaración editar

La declaración de una función generalmente tiene la siguiente estructura:[2]

[Tipo de datos del resultado] subrutina [nombre de la función] ( [lista de parámetros] )
[Instrucciones a ejecutar como parte del cuerpo de la función.]
regresar [Dato a regresar como resultado]
fin_subrutina

El tipo de datos del resultado es uno de los indicadores de los tipos de datos primitivos soportados por el lenguaje de programación (entero, real, carácter, etc.), el nombre de la subrutina es cualquier nombre válido según las reglas del lenguaje y la palabra regresar al final de la subrutina sirve para especificar el dato que se debe regresar como resultado de la función. El dato regresado debe ser del tipo especificado en el tipo de retorno de la función o de lo contrario el compilador reportará un error.

La estructura de los procedimientos es igual a la estructura de las funciones. En su declaración simplemente se omiten el tipo de datos del resultado y la instrucción regresar al final del cuerpo de la subrutina.

subrutina [nombre del procedimiento] ( [lista de parámetros] )
[Instrucciones a ejecutar como parte del cuerpo del procedimiento.]
fin_subrutina

Parámetros editar

Para poder realizar las tareas deseadas, las subrutinas deben recibir información del programa principal. Esa información se transfiere usando parámetros. Estos consisten de una lista de 0 o más variables declaradas en la cabecera, indicando el tipo de dato transferido y un nombre para poder usarlo.[1] Los elementos de la lista usualmente se separan con algún tipo de indicador como la coma (,). Los parámetros se consideran variables locales porque solo existen durante la ejecución del subprograma y solo el código en el cuerpo de este puede hacer uso de ellos.[3]

En el siguiente ejemplo se declara una función llamada área_triángulo que recibe dos parámetros, la base y la altura de un triángulo y regresa un número real con el área correspondiente:

// Función para calcular el área de un triángulo.
real subrutina área_triángulo (real base, real altura)

     regresar (base * altura) / 2

fin_subrutina

Cuando un programa invoca una subrutina, normalmente le entrega copias de los valores de los datos que le pasa en los parámetros. Esto significa que las subrutinas pueden alterar los valores de los parámetros sin afectar los valores en las variables usadas al invocarlos. Este concepto se llama «paso de parámetros por valor» y es el método usado con mayor frecuencia al trabajar con parámetros de tipos de datos primitivos. Otra forma de pasar parámetros consiste en proporcionar un apuntador a la variable que contiene el dato en vez de pasar una copia. En este caso el subprograma debe usar el apuntador para llegar al dato y los cambios que le haga serán visibles al resto del programa. Este método se conoce como «paso de parámetros por referencia» y se usa frecuentemente para trabajar con tipos de datos estructurados.[1]

Invocación editar

Una vez que una subrutina ha sido declarada, es posible usarla, ya sea en el programa principal o dentro de otras subrutinas. Si la subrutina es una función, se puede usar en cualquier lugar donde se puede usar una expresión del tipo de datos del resultado de la función. Si es un procedimiento, se puede usar en los lugares donde se pueden usar los otros tipos de instrucciones del lenguaje de programación, ya que representan un salto en el orden de ejecución de las instrucciones y el posterior regreso al punto de llamada.[3]

Para invocar una subrutina se debe especificar su nombre y una lista de valores para los parámetros. Los valores de los parámetros pueden ser constantes, variables, expresiones o el resultado de la invocación de otras funciones. Cuando se invoca la subrutina, el programa obtiene los valores de las variables, calcula los valores de las expresiones o llama a las funciones indicadas y obtiene su valor de retorno y asigna esos valores a las variables locales que crea con los nombres especificados en los parámetros de la declaración de la subrutina.[2]

En el siguiente ejemplo se invoca a una función predefinida llamada ln que recibe un número real como su parámetro y calcula su logaritmo natural. El valor de retorno de la función se asigna a una variable.

real resultado

resultado := ln (300.0)

En este otro ejemplo, para calcular la hipotenusa de un triángulo rectángulo, se invoca una función preexistente que recibe un número real y regresa la raíz cuadrada de ese número. El número real proporcionado como parámetro es el resultado de una expresión que regresa la suma de los cuadrados de los catetos del triángulo.

real cateto_a := 3.0
real cateto_b := 4.0

real hipotenusa := raíz_cuadrada (cateto_a ** 2 + cateto_b ** 2)

Muchos lenguajes de programación no proporcionan operadores para calcular potencias pero si proporcionan funciones predefinidas para realizar la operación. En el siguiente ejemplo se realiza el mismo cálculo del ejemplo anterior pero se usa una función para elevar los catetos al cuadrado. En este caso el lenguaje de programación primero ejecuta la función potencia en dos ocasiones diferentes para obtener los valores que regresa en cada caso y llama a la función raíz_cuadrada con el resultado de la suma de ambos.

real cateto_a := 3.0
real cateto_b := 4.0

real hipotenusa := raíz_cuadrada ( potencia(cateto_a, 2) + potencia(cateto_b, 2) )

Variables locales editar

Generalmente el cuerpo de las subrutinas de un programa consiste de un bloque de código del mismo tipo de los usados en las estructuras de control de flujo. Esto permite ejecutar múltiples instrucciones en el cuerpo de la función y declarar variables locales para almacenar información de trabajo y resultados parciales antes de regresar el resultado al programa principal.[2]

La función en el siguiente ejemplo calcula el área de un triángulo usando la fórmula de Herón. Como esa fórmula debe usar un valor parcial llamado «semiperímetro del triángulo» múltiples veces, se usa una variable local para calcularlo una sola vez.

// Función para calcular el área de un 
// triángulo usando la fórmula de Herón.
real subrutina área_triángulo (real lado_a, real lado_b, real lado_c)

     // Variable local para almacenar el semiperímetro
     real s

     // Cálculo del semiperímetro
     s := (lado_a + lado_b + lado_c) / 2
     
     // Cálculo del área usando el semiperímetro
     // y una función predefinida para calcular
     // la raíz cuadrada.
     regresar raíz_cuadrada ( s * (s - lado_a) * (s - lado_b) * (s - lado_c) )

fin_subrutina

Uso de variables globales editar

Además de los parámetros y las variables declaradas localmente, las subrutinas pueden usar y modificar las variables globales de un programa. Las variables globales le permite a múltiples subrutinas compartir información sin tener que pasarla como parámetros.[2] Los cambios que realizan las subrutinas a los valores de las variables globales se llaman «efectos colaterales» y normalmente se consideran una mala práctica de programación ya que dificultan la compresión y mantenibilidad de los programas.[4]

Bibliotecas de funciones editar

La mayoría de los ambientes de desarrollo proporciona mecanismos para definir múltiples funciones en un archivo y luego cargar ese archivo en un programa que usará las funciones. Estas colecciones frecuentemente se llaman bibliotecas de subrutinas y los lenguajes de programación proporcionan instrucciones especiales para incorporarlas en el programa principal. En el siguiente ejemplo se incorpora una biblioteca de subrutinas llamada áreas_polígonos.bib en el programa principal y luego se usa la función área_hexágono_regular, definida dentro de esa biblioteca, para calcular el área de una figura geométrica de ese tipo.

// Cargando biblioteca de funciones para usarlas en el programa.
cargar ("áreas_polígonos.bib")

real lado    := 5.0
real apotema := 12.0
real área

área := área_hexágono_regular (lado, apotema)

Las subrutinas y su agrupación en bibliotecas son unos de los principales mecanismos que proporcionan los lenguajes de programación para dividir los programas grandes en unidades más manejables, llamadas módulos.[2] Los módulos le facilitan a los programadores el comprender y modificar los programas[1] así como comprobar que son correctos y funcionan como es esperado.[3] También se usan en los lenguajes de programación para proporcionarle a los programadores un conjunto de funciones que realizan tareas comunes como el cálculo de funciones matemáticas complejas o el manejo de la entrada y salida de información.[2]

Resumen de la lección editar

  • Las subrutinas se invocan para ejecutar una tarea y una vez completada regresan el control al lugar de donde fueron llamadas.
  • A diferencia de los procedimientos, las funciones regresan un valor como resultado de su ejecución.
  • La declaración de una subrutina se compone de un encabezado y un cuerpo.
  • Una declaración de una subrutina tiene un tipo de datos de retorno, un nombre, una lista de parámetros y un bloque de código con el cuerpo.
  • La invocación de una subrutina es el lugar del programa desde el cual se utiliza.
  • Los parámetros se usan para transmitir información desde el programa principal hacia la subrutina.
  • Las funciones se pueden invocar en cualquier lugar donde es posible colocar una expresión.
  • Los procedimientos se pueden llamar desde cualquier lugar donde es posible colocar una instrucción.
  • Las subrutinas se pueden agrupar en bibliotecas que permiten reutilizarlas en múltiples programas.

Términos clave editar

Lecturas adicionales editar

Bibliografía editar

  1. 1,0 1,1 1,2 1,3 Brookshear, J. Glenn (2012). Computer Science: An overview [Introducción a la computación] (11.ª edición). Madrid, España: Pearson Educación, S. A. p. 704. ISBN 978-84-78-29139-7. 
  2. 2,0 2,1 2,2 2,3 2,4 2,5 Joyanes Aguilar, Luis (2013). Fundamentos generales de programación (1.ª edición). Ciudad de México, México: McGraw Hill. p. 368. ISBN 978-607-15-0818-8. 
  3. 3,0 3,1 3,2 Appleby, Doris; Vandekopple, Julius J. (1998). Programming Languages: Paradigm and practice [Lenguages de programación: Paradigma y práctica] (1.ª edición). México D. F., México: McGraw Hill. p. 492. ISBN 970-10-1945-8. 
  4. Deitel, H. M.; Deitel, P. J. (1995). C How to program [Cómo programar en C/C++] (2.ª edición). México: Prentice Hall Hispanoamericana, S. A. p. 927. ISBN 968-880-471-1. 


Proyecto: Fundamentos de programación
Anterior: Evaluación de la lección 7 — Subrutinas — Siguiente: Evaluación de la lección 8