Los valores predeterminados de los parámetros se pueden indicar para cualquiera de los parámetros de una función asignando un valor al parámetro en la lista de parámetros, justo después de la anotación de tipo del parámetro. Cuando se especifica un valor predeterminado para un parámetro, quien llama a la función puede omitir ese parámetro al llamarla y, en su lugar, se usará el valor predeterminado.
func greeting(name: String = "guest", duration: Int = 2) -> String {
"Welcome, \(name). Enjoy your \(duration) night stay."
}
greeting(name: "Bobo", duration: 7)
// Returns "Welcome, Bobo. Enjoy your 7 night stay."
greeting(duration: 3)
// Returns "Welcome, guest. Enjoy your 3 night stay."
greeting(name: "Wynona")
// Returns "Welcome, Wynona. Enjoy your 2 night stay."
greeting()
// Returns "Welcome, guest. Enjoy your 2 night stay."
Los parámetros variádicos permiten que una función acepte cero o más valores de un tipo determinado en un solo parámetro.
Un parámetro variádico se define añadiendo tres puntos (...) a la anotación de tipo del parámetro.
Dentro del cuerpo de la función, Swift pone estos valores a tu disposición como un array del tipo determinado:
import Foundation
func geometricMean(_ numbers: Double...) -> Double {
var total = 1.0
for number in numbers {
total *= number
}
return pow(total, 1.0 / Double(numbers.count))
}
let result = geometricMean(1, 2, 3, 4, 5)
// result is 2.605171084697352
Si una función incluye parámetros adicionales después de un parámetro variádico, el primer parámetro que sigue al variádico debe tener una etiqueta de argumento explícita para que Swift sepa dónde termina la lista de argumentos variádicos.
Dentro del cuerpo de una función, los parámetros se tratan como constantes, no como variables; intentar modificar el valor de un parámetro provoca un error en tiempo de compilación. Si una función quiere modificar el valor de un parámetro, debe usar un parámetro in-out para hacer explícita esta mutabilidad.
Para usar parámetros in-out, hay que tener claras tres cosas:
inout entre el : y el nombre del tipo en la anotación de tipo del parámetro.& en la llamada a la función, lo que lo marca explícitamente como modificable.Cuando se hace esto, la función crea una copia interna del parámetro in-out, la modifica según lo indicado en el cuerpo de la función y, cuando la función termina, copia el valor modificado de vuelta en la variable que se pasó.
func updateVersion(_ record: inout (version: Int, title: String)) {
record.version += 1
}
var dbRecord = (version: 2, title: "Exercism")
updateVersion(&dbRecord)
// dbRecord is now (3, "Exercism")
Hay un par de reglas adicionales que conviene conocer sobre los parámetros in-out.
1 Dentro de una función con parámetros in-out, no puedes hacer referencia a la variable que se pasó como parámetro in-out.
2. La misma variable no se puede pasar como varios parámetros in-out en la misma función.
Por ejemplo, `inoutFunc(&mutVar, &mutVar)` provoca un error del compilador.
En Swift, puedes definir funciones dentro de otras funciones. Estas se conocen como funciones anidadas.
Las funciones anidadas se usan habitualmente como auxiliares privados que realizan tareas concretas para la función que las contiene sin recargar el ámbito exterior:
func makeNumber(_ number: Int) -> Int {
func double(_ x: Int) -> Int {
x * 2
}
func increment(_ x: Int) -> Int {
x + 1
}
return number.isMultiple(of: 2) ? increment(double(number)) : double(number)
}
print(makeNumber(3)) // Prints 6
print(makeNumber(4)) // Prints 9
Las funciones anidadas se comportan como funciones estándar, pero su visibilidad se limita al cuerpo de la función que las contiene.
En este ejercicio vas a escribir algo más de código para ayudarte a cocinar tu magnífica lasaña, sacada de tu libro de cocina favorito.
Tienes cinco tareas, todas relacionadas con el tiempo empleado en cocinar la lasaña.
Quieres escribir una función remainingMinutesInOven mejorada que reciba como parámetro el número de minutos transcurridos que la lasaña lleva en el horno y devuelva cuántos minutos le quedan todavía por permanecer en el horno, según el tiempo esperado en minutos de la tarea anterior.
Antes, te apoyabas en un valor constante, expectedMinutesInOven, que venía de fuera de la función remainingMinutesInOven.
Eso resultaba, por un lado, un poco demasiado enrevesado para tu gusto y, por otro, no era lo bastante flexible, ya que no te permitía cambiar el tiempo esperado en el horno.
Para poner un poco de orden, define la función remainingMinutesInOven que reciba como parámetro el número de minutos transcurridos que la lasaña lleva en el horno, además de un parámetro expectedMinutesInOven con un valor predeterminado de 40.
Tu función debe devolver cuántos minutos le quedan todavía a la lasaña por permanecer en el horno, según el tiempo esperado en minutos de la tarea anterior.
remainingMinutesInOven(elapsedMinutes: 30)
// Returns 10
remainingMinutesInOven(elapsedMinutes: 30, expectedMinutesInOven: 75)
// Returns 45
Antes habías escrito una función preparationTimeInMinutes que recibe como parámetro el número de capas que añadiste a la lasaña y devuelve cuántos minutos dedicaste a prepararla, suponiendo que cada capa te lleva 2 minutos preparar.
Sin embargo, no estás del todo contento con esta función, ya que tienes que contar tú mismo el número de capas de tu lasaña antes de poder llamarla, ¿y quién tiene tiempo para todo eso?
Para ponértelo más fácil, escribe una función, preparationTimeInMinutes, que reciba un parámetro String variádico, layers, donde enumeras las distintas capas de tu lasaña.
La función contará entonces el número de capas de tu lasaña y devolverá el tiempo de preparación necesario.
preparationTimeInMinutes(layers: "sauce", "noodles")
// Returns 4
preparationTimeInMinutes(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns 24
Antes de empezar a montar tu lasaña, quieres asegurarte de tener suficiente salsa y fideos para construir la lasaña de tus sueños. Por cada capa de fideos de tu lasaña, necesitarás 3 fideos. Por cada capa de salsa de tu lasaña, necesitarás 0,2 litros de salsa.
Define la función quantities que reciba un parámetro String variádico, layers, donde enumeras las distintas capas de tu lasaña.
La función determinará entonces la cantidad de fideos y salsa necesaria para preparar tu comida. El resultado debe devolverse en una tupla de tipo (noodles: Int, sauce: Double).
quantities(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns (noodles: 9, sauce: 0.8)
quantities(layers: "sauce", "noodles", "sauce", "noodles", "meat", "noodles", "mozzarella")
// Returns (noodles: 9, sauce: 0.4)
Por desgracia, la salsa que tienes a mano tiene el volumen indicado en onzas líquidas en lugar de en litros.
Para ayudarte a saber si tienes suficiente salsa a mano, escribe una función, toOz, que reciba un parámetro tupla in-out, (noodles: Int, sauce: Double), y convierta la cantidad de salsa a onzas líquidas.
Ten en cuenta que hay 33,814 onzas líquidas por litro.
var amount = (noodles: 9, sauce: 0.8)
toOz(&amount)
amount
// Returns (noodles: 9, sauce: 27.0512)
Por último, quieres saber qué tipo de vino servir con tu lasaña.
Has oído que deberías servir vino blanco si en la lasaña hay más mozzarella, ricotta y béchamel que carne y salsa, y vino tinto en caso contrario.
Escribe una función redWine que reciba un parámetro String variádico, layers, donde enumeras las distintas capas de tu lasaña.
La función usará cinco funciones anidadas para determinar el número de capas de mozzarella, ricotta, béchamel, salsa y carne de la lasaña, y comparará el número de capas para decidir si debe servirse vino tinto, devolviendo true si es así y false si no.
redWine(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns true
redWine(layers: "sauce", "noodles", "béchamel", "meat", "mozzarella", "noodles", "ricotta", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns false
Regístrate en Exercism para aprender y dominar Swift con 35 conceptos116 ejercicios y mentoría humana real, todo gratis.