Puedes dar valores predeterminados de los parámetros a cualquiera de los parámetros de una función asignando un valor al parámetro en la lista de parámetros, después de la anotación de tipo de ese parámetro. Cuando se especifica un valor predeterminado, quien llama a la función puede omitir ese parámetro al llamarla y se usará el valor predeterminado en su lugar.
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 especificado para un solo parámetro.
Para definir un parámetro variádico, agrega tres puntos (...) a la anotación de tipo del parámetro.
Dentro del cuerpo de la función, Swift te da estos valores como un array del tipo especificado:
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 parámetro 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 genera 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, quien escribe el código debe estar seguro de tres cosas:
inout entre los : y el nombre del tipo en la anotación de tipo del parámetro.& en la llamada a la función, marcándola 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 puede pasarse como varios parámetros in-out en la misma función.
Por ejemplo, `inoutFunc(&mutVar, &mutVar)` genera un error del compilador.
En Swift, puedes definir funciones dentro de otras funciones. Estas se conocen como funciones anidadas.
Las funciones anidadas se usan comúnmente como auxiliares privados que realizan tareas específicas para la función que las contiene sin saturar el ámbito externo:
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 está restringida al cuerpo de la función que las contiene.
En este ejercicio vas a escribir un poco más de código para ayudarte a cocinar esa estupenda lasaña de tu libro de cocina favorito.
Tienes cinco tareas, todas relacionadas con el tiempo que pasas cocinando la lasaña.
Quieres escribir una versión mejorada de la función remainingMinutesInOven que tome como parámetro el número de minutos transcurridos que la lasaña ha estado en el horno y devuelva cuántos minutos aún debe permanecer la lasaña en el horno, según el tiempo esperado en minutos de la tarea anterior.
Antes, dependías de un valor constante, expectedMinutesInOven, que venía de fuera de la función remainingMinutesInOven.
Eso era un poco demasiado desordenado para tu gusto y no lo bastante flexible, ya que no te permitía cambiar el tiempo esperado en el horno.
Para ordenar un poco las cosas, define la función remainingMinutesInOven que toma como parámetro el número de minutos transcurridos que la lasaña ha estado en el horno, así como un parámetro expectedMinutesInOven que tiene un valor predeterminado de 40.
Tu función debe devolver cuántos minutos aún debe permanecer la lasaña 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 toma como parámetro el número de capas que le agregaste a la lasaña y devuelve cuántos minutos pasaste preparando la lasaña, suponiendo que cada capa te toma 2 minutos preparar.
Sin embargo, no te convence del todo esta función, ya que tienes que contar tú mismo el número de capas de tu lasaña antes de poder llamar a esta función, y ¿quién tiene tiempo para todo eso?
Para facilitarte las cosas, escribe una función, preparationTimeInMinutes, que tome un parámetro variádico String, layers, donde enumeras las diferentes capas de tu lasaña.
Luego, la función contará el número de capas de tu lasaña y devolverá la cantidad de tiempo de preparación necesaria.
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 armar 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 en tu lasaña, necesitarás 3 fideos. Por cada capa de salsa en tu lasaña, necesitarás 0.2 litros de salsa.
Define la función quantities que toma un parámetro variádico String, layers, donde enumeras las diferentes capas de tu lasaña.
Luego, la función determinará la cantidad de fideos y salsa necesarias 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)
Lamentablemente, la salsa que tienes a mano tiene el volumen indicado en onzas líquidas en lugar de litros.
Para ayudarte a saber si tienes suficiente salsa a mano, escribe una función, toOz, que toma un parámetro de tupla de entrada y salida, (noodles: Int, sauce: Double), y convierte 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)
Finalmente, quieres saber qué tipo de vino servir con tu lasaña.
Has oído que deberías servir vino blanco si hay más mozzarella, ricota y bechamel en la lasaña que carne y salsa, y vino tinto de lo contrario.
Escribe una función redWine que tome un parámetro variádico String, layers, donde enumeras las diferentes capas de tu lasaña.
La función usará cinco funciones anidadas para determinar el número de capas de mozzarella, ricota, bechamel, salsa y carne en la lasaña, y comparar los números de capas para determinar si se debe servir 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.