Saltar al contenido
KodigoSwift

Tutorial Swift – Funciones

Funciones

En el Tutorial Swift de hoy aprenderemos sobre las funciones, y esto sería lo mismo que decir que aprenderemos sobre los métodos de las clases ya que en Swift las funciones y los métodos comparten la mayoría de sus características, de hecho se declaran de la misma manera, por lo que todo lo expuesto aquí también nos servirá para cuando lleguemos a las clases, los objetos, la herencia, etc.

Como siempre veremos mediante ejemplos las formas no usuales que adoptan las funciones en Swift, muy elegantes a mi modo de ver.

Definiendo y llamando funciones

La definición de funciones no es algo complejo y apartando la sintaxis, tanto la definición como la llamada, comparten la mayoría de características con el resto de formas que encontramos en otros lenguajes de programación. Sí, me refiero a que cuentan con un nombre, parámetros de entrada y valores de retorno, un ejemplo podría ser el siguiente:

…la salida en pantalla sería:

Parámetros de Funciones y Valores de Retorno

Los parámetros de la función y los valores de retorno son extremadamente flexibles en Swift. Podemos definir cualquier cosa, desde una función utilitaria simple y con un solo parámetro sin nombre, hasta una función compleja con nombres de parámetros expresivos y diferentes opciones.

Funciones sin parámetros

No es obligatorio que especifiquemos parámetros de entrada en una función. Aquí vemos una función sin parámetros, que devuelve siempre el mismo mensaje String cada vez que es llamada:

…salida en pantalla más que evidente.

La definición de esta función aún necesita paréntesis luego del nombre, incluso cuando esta no recibirá jamás un parámetro. La función también es precedida por un par de paréntesis vacíos cuando la función es llamada en la última línea.

Funciones con múltiples parámetros

Las funciones pueden tener múltiples parámetros de entrada, estos se escriben dentro de los paréntesis que siguen al nombre y separados por comas.

El siguiente ejemplo muestra una función que toma dos parámetros, el nombre de una persona y un valor booleano que representa si esta persona ya fue saludada o no, finaliza su ejecución devolviendo el nombre concatenado a un mensaje:

…analicemos más de cerca la firma de esta función:

…comenzamos con la palabra clave func que como ya deberán de haberse dado cuenta la utilizamos para declarar una función, le sigue el nombre de la función y junto a este los paréntesis que contienen los parámetros, dos en este caso, el primero personName de tipo String, el segundo alreadyGreeted de tipo booleano, terminamos con la flecha de retorno (->) seguido del tipo de dato que será devuelto, en este caso un valor de tipo String.

En la última línea de este ejemplo hacemos una llamada a nuestra función personName y a su vez dentro de la función print para devolver en pantalla el valor correspondiente. En esta misma línea nos encontramos con una característica digna de mencionar y es que cuando tenemos más de un parámetro, cualquier otro, posterior al primero, tiene que ir etiquetado con el nombre asignado a ese parámetro en la firma de la función, por este motivo, es que solamente escribimos alreadyGreeted: true en el segundo parámetro, mientras en el primero escribimos directamente el valor.

Funciones con múltiples valores de retorno

En Swift podemos valernos de una tupla para enviar múltiples valores de una vez, es decir en una tupla contendríamos varios valores y los devolveríamos en una sola orden de retorno.

Veamos un ejemplo:

Luego que la función minMac determina el mínimo y el máximo de los números insertados, esta devuelve una tupla de dos valores Int, cada uno etiquetado con las etiquetas currentMin y currentMax respectivamente, esto permite que podamos acceder a sus valores mediante las etiquetas cuando consultemos el valor de retorno, por lo que el siguiente código sería perfectamente válido:

…la salida en pantalla sería:

Valores de retorno opcionales

Continuando con el último ejemplo, analicemos que sucedería si hubiera una posibilidad de que la función no devolviera un valor, si ante cierto evento no hubiera un resultado a retornar. En este caso lo que pudieramos hacer sería especificar en la firma de la función que la tupla de retorno es opcional, que puede ser nil, para esto colocamos el signo de interrogación al final de la declaración de retorno, de esta manera: (Int, Int)? o (String, Int, Bool)?, según sea el caso.

Creo que es prudente comentar en este punto que la expresión anterior no significa lo mismo que (Int?, Int?) o (Int?, Int), en ambos casos los valores específicos de la tupla son los que pueden ser o no opcionales, cuando declaramos (Int, Int)? estamos diciendo al compilador que la tupla entera puede ser opcional.

Nuestra función minMax devuelve una tupla con los resultados de su operación, pero en esta no se verifica si el contenido del Array de entrada está vacío o no, a continuación una versión mejorada:

…en la primera línea vemos como hemos añadido el signo de interrogación al final de la firma, indicando que el valor de retorno es opcional. Luego en la línea 3 verificamos que el array que nos han pasado como parámetro no esté vacío, de ser así devolvemos nil y abortamos la ejecución de esta función. En la línea 26 verificamos mediante una orden if let que el valor devuelto por nuestra función no sea nil, en caso negativo imprimimos los resultados, en caso positivo pues un mensaje de error.

Nombres de parámetros

Los parámetros de las funciones tienen un nombre de parámetro externo y uno local. El nombre externo de un parámetro es usado para etiquetar los valores que se pasan a la función cuando esta se llama, por su parte el nombre local es usado en la implementación de la función, internamente.

En la última línea vemos otra característica de las funciones y es que por defecto en el primer parámetro se omite el nombre externo del mismo, el segundo y demás parámetros usan su nombre local como su nombre externo, aunque como veremos a continuación esto último es algo flexible.

Nombres externos de parámetros

Especificamos el nombre externo de una función escribiéndolo antes del nombre local, separado por un espacio:

…en la línea 5 hemos especificado externalParameterName como un nombre externo, a este solamente podemos hacer referencia desde el exterior como podemos observar en la línea 13.

Esta característica aparte de la flexibilidad evidente que nos brinda, también nos permite crear llamadas a función de este tipo:

En este ejemplo podemos ver como localmente usamos los nombres velocity y acceleration que son más que descriptivos en su representación, mientras que la interfaz externa de la función maneja nombres que en conjunto con el nombre de la función y los otros parámetros conforman una sentencia mucho más legible como podemos observar en la última línea, la cual pudiéramos leer de manera similar al mensaje que se imprime en pantalla:

…nosotros leeríamos:

movingForward withVelocityOf 150 andAccelerationOf 10

…como podrán percatarse es una declaración que al leerla nos es familiar, la entendemos sin problemas, tal parece una oración, es prácticamente el mismo mensaje que imprimimos en consola.

Podemos en caso de ser necesario omitir el nombre externo de los parámetros, es decir solamente tendríamos que especificar el valor tal y como hacemos en otros lenguajes de programación:

…en la primera línea podemos ver que en lugar de escribir el nombre externo del segundo parámetro solamente escribimos el caracter “_” (guión bajo) y así haremos por cada parámetro subsiguiente, en la última línea vemos el resultado esperado.

Valores por defecto

A las funciones en Swift también le podemos especificar valores por defecto a los parámetros que esta recibe y como era de esperar es algo bien sencillo, esto lo logramos especificando el valor luego del tipo de dato, aquí un ejemplo:

…sobre este ejemplo no hay nada que decir, los comentarios en el código son más que suficiente.

Función variádica

Una función variádica acepta cero o más parámetros de un tipo específico. Un parámetro variádico se usa para especificar que al parámetro en cuestión se le puede pasar un número variable de valores al momento de ser llamada la función. Declaramos parámetros variádicos insertando tres puntos (…) después del tipo de dato del parámetro.

Los valores pasados a un parámetro variádico se ponen a disposición dentro del cuerpo de la función a través de un arreglo. Por ejemplo, un parámetro variádico llamado numbers de tipo Double… se encuentra disponible dentro del cuerpo de la función como un arreglo constante llamado numbers de tipo [Double].

En el siguiente ejemplo veremos una función que calcula el average de una serie de números, la lista de números pasados no tiene límites especificados:

…en la línea 5 tenemos la firma de nuestra función y su parámetro variádico, luego nos valemos de un ciclo for-in para ir iterando de manera dinámica por cada elemento de nuestro arreglo, elementos que vamos sumando y almacenando en la variable total, la cual luego dividimos por la cantidad de valores insertados y devolvemos el valor resultante. La salida en pantalla sería:

Constantes y parámetros variables

Los parámetros de las funciones son constantes por defecto y tratar de modificar alguno de ellos desde el interior de una función produce un error en tiempo de compilación, impidiendo que podamos cambiar su valor por error.

Sin embargo, a veces es útil tener una copia variable del valor de un parámetro. Podemos evitar definir una nueva variable dentro de la función especificando uno o más parámetros como parámetros variables. Los parámetros variables están disponibles como variables y no como constantes, y nos dan una copia modificable del valor del parámetro con el cual podremos trabajar y modificar.

Definimos parámetros variables haciendo uso de la palabra clave var anteponiéndola al nombre del parámetro, como una variable común, aquí un ejemplo:

…la salida en pantalla:

En este ejemplo como podrán observar en la línea 19 el parámetro text es variable y totalmente funcional.

Aunque parezca evidente quiero hacer notar que los cambios que se realicen en un parámetro variable no persisten más allá del final de cada llamada a función, y tampoco son visibles fuera del cuerpo de la misma. Un parámetro variable sólo existe durante el tiempo de vida de la función.

Parámetros In-Out

Los parámetros variables, como se han descrito anteriormente, sólo se puede cambiar dentro de la propia función. Si se desea que una función modifique el valor de un parámetro, y que esos cambios persistan después que la llamada a la función haya terminado, tendríamos que definir ese parámetro como un parámetro in-out.

Declaramos un parámetro como in-out mediante la palabra clave inout al inicio de la definición del parámetro. El valor de un parámetro In-Out es pasado a la función, es modificado por la función y se retorna en reemplazo del valor original. Al llamar una función cuyos parámetros son inout tenemos que especificar el signo & antes del nombre de la variable.

Lógicamente, solamente podemos pasar variables como parámetro In-Out, no pueden ser constantes ni valores literales ya que estos no pueden ser modificados. Los parámetros In-Out tampoco pueden tener valores por defecto ni pueden ser variádicos, ni ser marcados como var o let.

Aquí tenemos un ejemplo:

…la salida en pantalla:

En esta función hacemos uso de parámetros In-Out donde efectuamos un cambio de valores, modificando cada variable con el valor de la otra sin necesidad de retornar ningún valor, como si estuviésemos accediendo directamente a su posición de memoria. Esta idea me viene a la mente ya que la línea 21 me resulta muy familiar, los parámetros que pasamos al momento de llamar la función, ambos con su signo ampersand (&), me recuerda mucho a C / C++ y esos casos donde pasábamos la dirección de memoria de una variable, quizás sea una característica heredada.

Creo que en este artículo podemos constatar cuan versátil es Swift como lenguaje y cuanto podemos hacer con las funciones.

Falta aún mucho por aprender en nuestro camino a convertirnos en iOS Developer. Suscríbete a nuestra lista de correo mediante el formulario en el panel derecho y síguenos en nuestras redes sociales. Mantente así al tanto de todas nuestras publicaciones futuras.

Espero que todo cuanto se ha dicho aquí, de una forma u otra le haya servido de aprendizaje, de referencia, que haya valido su preciado tiempo.

Este artículo, al igual que el resto, será revisado con cierta frecuencia en pos de mantener un contenido de calidad y actualizado.

Cualquier sugerencia, ya sea errores a corregir, información o ejemplos a añadir será, más que bienvenida, necesaria!

RECIBE CONTENIDO SIMILAR EN TU CORREO

RECIBE CONTENIDO SIMILAR EN TU CORREO

Suscríbete a nuestra lista de correo y mantente actualizado con las nuevas publicaciones.

Se ha suscrito correctamente!