Advertisement
  1. Code
  2. Mobile Development
  3. iOS Development

Swift Desde Cero: Una Introducción a Funciones

Scroll to top
Read Time: 10 min
This post is part of a series called Swift From Scratch.
Swift From Scratch: Optionals and Control Flow
Swift From Scratch: Function Parameters, Types, and Nesting

() translation by (you can also view the original English article)

Para hacer cualquier cosa en Swift, necesitarás aprender los pros y contras de las funciones. Las funciones son excepcionalmente poderosas y flexibles en Swift. Los básicos son simples---especialmente si has trabajado con otros lenguajes de programación anteriormente---pero debido a la sintaxis flexible de Swift puede volverse complejo si no estás familiarizado con los básicos.

En este artículo, nos enfocaremos en esos básicos primero y exploraremos la sintaxis más compleja y casos de usos en el siguiente artículo. Es importante que no ignores los básicos ya que son esenciales para entender de donde viene el poder de una función en Swift. Comencemos con un ejemplo para seccionar la anatomía de una función en Swift.

1. Aprende por el Ejemplo

Una función no es nada más que un bloque de código que puede ser ejecutado siempre que sea necesario. Me gustaría comenzar con un ejemplo para discutir la anatomía básica de una función Swift. Ejecuta Xcode y crea un nuevo playground. Agrega la siguiente definición de función al playground.

1
func printHelloWorld() {
2
    println("Hello World!")
3
}

Una función comienza con la palabra clave func y es seguida por el nombre de la función, printHelloWorld en nuestro ejemplo. Como muchos otros lenguajes, el nombre de la función es seguido por un par de paréntesis que contienen los parámetros de la función, la entrada de la función.

El cuerpo de la función es envuelto en un par de llaves. La función printHelloWorld contiene una declaración en la cuál imprimimos la cadena Hello World! en la salida estándar. Así es como luce una función básica en Swift. La sintaxis es simple, limpia y minimalista.

Puedes invocar la función tecleando el nombre de la función, seguido por un par de paréntesis.

1
printHelloWorld()

2. Parámetros

Hagamos el ejemplo de arriba un poco más complejo agregando parámetros a la definición de la función. Esto simplemente significa que proporcionamos a la función valores que puede usar en el cuerpo de la función. En el siguiente ejemplo, definimos la función printMessage, que acepta un parámetro, message, del tipo String.

1
func printMessage(message: String) {
2
    println(message)
3
}

Una función puede aceptar múltiples parámetros o valores de entrada. Los parámetros son envueltos por los paréntesis que siguen al nombre de la función. El nombre del parámetro es seguido por una coma y el tipo del parámetro. Como recuerdas, esto es muy similar a declarar una variable o constante. Eso simplemente dice que el parámetro message es de tipo String.

En vez de imprimir una cadena codificada como lo hicimos en la función printHelloWorld, imprimimos el valor del parámetro message. Esto hace a la función flexible y más útil.

Invocar a la función es muy similar a lo que vimos anteriormente. La única diferencia es que le pasamos un argumento cuando invocamos la función.

1
printMessage("Hello World!")

Nota que los términos parámetros y argumentos son frecuentemente usados de manera intercambiable, pero hay una sutil diferencia semántica en Swift. En Swift, los parámetros son valores especificados en la definición de función mientras que los argumentos son los valores pasados a la función cuando es invocada.

Parámetros Múltiples

Como mencioné anteriormente, la sintaxis de las funciones es muy flexible y no debería sorprenderte de que es perfectamente posible pasar múltiples argumentos a una función. En el siguiente ejemplo, creamos una variación de la función printMessage que nos permite imprimir el mensaje múltiples veces.

1
func printMessage(message: String, times: Int) {
2
    for i in 0..<times {
3
        println("\(i) \(message)")
4
    }
5
}

Mientras que el nombre de la función es idéntico al de la función original printMessage, el tipo de función es diferente. Es importante que entiendas la sentencia previa. Léela de nuevo.

Cada función tiene un tipo, consistente de los tipos de parámetros y el tipo de retorno. Exploraremos los tipos de retorno en un momento. Las funciones pueden tener el mismo nombre mientra su tipo sea diferente como se muestra en las dos definiciones de funciones previas.

El tipo de la primera función es (String) -> () mientras que el tipo de la segunda función es (String, Int) -> (). El nombre de ambas funciones es el mismo. No te preocupes por el símbolo ->. Su significado se volverá más claro en unos cuantos momentos cuando discutamos los tipos de retorno.

La segunda función printMessage define dos parámetros, message de tipo String y times de tipo Int. Esta definición ilustra una de las características que Swift ha adoptado de Objective-C, nombres legibles de función/método. Mientras que el nombre de la función es printMessage, leyendo los nombres de los parámetros de la función, es fácil entender lo que se supone que hace la función.

En la segunda función printMessage, creamos un ciclo for-in para imprimir la cadena message times veces. Usamos el operador de rango medio-abierto, ..<, como vimos antes en la serie.

Cuando comenzamos a teclear printMessage en el playground, Xcode muestra ambas funciones en el menú autocompletar. Gracias al tipo de la función, es fácil elegir la función en la que estamos interesados. Llamar a la segunda función printMessage es tan simple como:

1
printMessage("Hello World", 3)

Valores Por Defecto

Una de mis características favoritas es la habilidad de definir valores para parámetros. Esto podrá sonar absurdo si vienes de un lenguaje que ha tenido esta característica por años, pero es muy grandioso si has estado trabajando con C y Objective-C por muchos años.

En corto, Swift permite a los desarrolladores definir valores por defecto para los parámetros de una función. Definamos una nueva función que imprima la fecha actual en un formato específico. Asegúrate de que agregas la siguiente declaración de importación encima de tu playground para importar el framework UIKit.

1
import UIKit

Primero definamos la función printDate sin hacer uso de valores por defecto para cualquiera de los parámetros.

1
func printDate(date: NSDate, format: String) {
2
    let dateFormatter = NSDateFormatter()
3
    dateFormatter.dateFormat = format
4
    println(dateFormatter.stringFromDate(date))
5
}

Si no estás familiarizado con el framework Foundation y no estás entendiendo qué está pasando en el cuerpo de la función, está bien. El foco de este ejemplo no está en la implementación de formatear la fecha. En printDate, usamos el valor del parámetro format para fomatear el valor de date. Si no pasamos el valor para el parámetro format, Swift nos dejará saber arrojando un error.

Podemos remediar esto definiendo un valor por defecto para el segundo parámetro de la función como se muestra en la definición actualizada de la función abajo.

1
func printDate(date: NSDate, format: String = "YY/MM/dd") {
2
    let dateFormatter = NSDateFormatter()
3
    dateFormatter.dateFormat = format
4
    println(dateFormatter.stringFromDate(date))
5
}

Definiendo un valor por defecto es tan simple como especificar el valor en la lista de parámetros en la definición de la función. El resultado es que Swift ya no se quejará y el error desaparece.

1
printDate(NSDate())

¿Qué si queremos pasar el valor para el parámetro format? Probemos y veamos lo que nos dice Swift.

Debido a que el parámetro format tiene un valor por defecto y por lo tanto es opcional, necesitamos pasar el nombre del argumento para decirle a Swift a qué parámetro nos estamos refiriendo. El  arreglo es muy sencillo como puedes ver abajo.

1
printDate(NSDate(), format: "dd/MM/YY")

Nota que Apple recomienda posicionar los parámetros con un valor por defecto al final de la lista de parámetros. Esto es ciertamente una buena idea y común en la mayoría de los otros lenguajes de programación que soportan parámetros opcionales.

3. Tipo de Retorno

Las funciones que hemos visto hasta ahora no nos regresan nada cuando las invocamos. Hagamos más útil la función printDate devolviendo la fecha formateada como string, en vez de imprimir la fecha formateada desde la función. Esto requiere dos cambios como puedes ver abajo.

1
func printDate(date: NSDate, format: String = "YY/MM/dd") -> String {
2
    let dateFormatter = NSDateFormatter()
3
    dateFormatter.dateFormat = format
4
    return dateFormatter.stringFromDate(date)
5
}

La primera cosa que cambiamos es la definición de la función. Después de la lista de parámetros especificamos el tipo de retorno, String. El tipo de retorno es precedido por el símbolo ->. Si has trabajado con CoffeeScript, entonces esto lucirá familiar.

En lugar de imprimir la fecha formateada usando la función println, usamos la palabra clave return para devolver el valor desde la función. Eso es todo lo que necesitamos hacer. Probemos.

1
let formattedDate = printDate(NSDate(), format: "dd/MM/YY")
2
3
println(formattedDate)

Invocamos la función printDate, almacenamos el valor devuelto en la constante formattedDate, e imprimimos el valor de formattedDate en la salida estándar. Nota que el nombre de la función printDate ya no refleja lo que hace por lo que quisieras cambiarla a formatDate.

Sin Tipo de Retorno

Las otras funciones que definimos en este tutorial no tenían un tipo de retorno. Cuando una función no tiene un tipo de retorno, no es necesario incluir el símbolo -> en la definición de función.

Unos cuantos párrafos antes, te dije que ninguna de las funciones que habíamos definido nos regresaban un valor. Eso de hecho no es del todo cierto. Déjame explicar los detalles con un experimento. Agrega la siguiente línea a tu playground y mira lo que ocurre.

Esto es interesante. Swift no tiene un problema cuando almacenamos el valor de retorno de la función printHelloWorld en una constante, pero se queja si no puede inferir el tipo del value constante.

¿Qué está pasando aquí? Cada función en Swift devuelve un valor, incluso si no definimos un tipo de retorno en la definición de la función. Cuando una función no especifica explícitamente un valor de retorno, la función devuelve implícitamente Void, que es equivalente a una tupla vacía, o () para corto. Puedes ver esto en la salida del panel del playground como se muestra en la captura de arriba.

Podemos deshacernos de la advertencia de arriba declarando de manera explícita el tipo de value, una tupla vacía. Estoy de acuerdo de que no es muy útil almacenar una tupla vacía en una constante, pero ilustra que toda función tiene un valor de retorno.

1
let value: () = printHelloWorld()

Tuplas

Otra gran característica de Swift es la habilidad para devolver múltiples valores desde una función devolviendo una tupla. El siguiente ejemplo ilustra cómo funciona esto. Déjame repetir que no es importante que entiendas cómo hace este trabajo la función timeComponentsForDate. El foco es el valor de retorno de la función timeComponentsForDate, una tupla con tres elementos.

1
func timeComponentsForDate(date: NSDate) -> (hour: Int, minute: Int, second: Int) {
2
    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)
3
    let hour = dateComponents.hour
4
    let minute = dateComponents.minute
5
    let second = dateComponents.second
6
    return (hour, minute, second)
7
}

La función acepta un argumento, una instancia NSDate, y regresa una tupla con tres valores etiquetados. Etiquetar los valores de la tupla es solo por conveniencia, es posible omitir las etiquetas.

1
func timeComponentsForDate(date: NSDate) -> (Int, Int, Int) {
2
    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)
3
    let hour = dateComponents.hour
4
    let minute = dateComponents.minute
5
    let second = dateComponents.second
6
    return (hour, minute, second)
7
}

Sin embargo, como el siguiente ejemplo ilustra, etiquetar los valores de la tupla devuelta de la función es muy conveniente y hace tu código más fácil de entender.

1
let timeComponents = timeComponentsForDate(NSDate())
2
3
println(timeComponents.hour)
4
println(timeComponents.minute)
5
println(timeComponents.second)

También es posible devolver un valor opcional desde una función si hay escenarios en los cuales la función no tiene valor para devolver. Esto es tan simple como definir el tipo de retorno de la función como opcional como se muestra abajo.

1
func timeComponentsForDate(date: NSDate) -> (hour: Int, minute: Int, second: Int)? {
2
    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)
3
    let hour = dateComponents.hour
4
    let minute = dateComponents.minute
5
    let second = dateComponents.second
6
    return (hour, minute, second)
7
}

Conclusión

En este tutorial nos hemos enfocado en los básicos de funciones en Swift. Es importante que entiendas la sintaxis de funciones, por que el siguiente artículo exploraremos funciones más avanzadas que se construyen sobre lo que hemos cubierto en este tutorial.

Te aliento a leer el artículo de nuevo si es necesario y, más importante, escribir unas cuantas funciones en un playgroud para familiarizarte con la sintaxis. Los básicos son muy sencillos de entender, pero solo  los entiendes practicando.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.