Si l'on retire tous les noms et les étiquettes d'une signature de fonction Swift, il ne reste que le type de la fonction.
func shoppingList(item: String, quantity: Int) -> String {
"You need to buy \(quantity) \(item)."
}
// shoppingList: (String, Int) -> String
func repeater(_ phrase: String, times: Int) -> String {
var result = ""
for _ in 1...times {
result += phrase
}
return result
}
// repeater: (String, Int) -> String
func printString(line: String) {
print(line)
}
// printString: (String) -> ()
Remarque que les types des deux premières fonctions sont identiques, (String, Int) -> String, même si les deux signatures sont différentes et que les deux fonctions se comportent de façon très différente. Toutes les deux prennent une String et un Int en entrée et renvoient une String. Et comme on peut le voir avec le type de la troisième fonction, même si le corps de la fonction ne semble rien renvoyer, il renvoie en fait implicitement (), la seule valeur de type Void.
Ces types de fonctions s'utilisent exactement comme n'importe quel autre type en Swift : on peut par exemple les utiliser dans la déclaration de variables ou de constantes. Et comme les fonctions sont des valeurs en Swift, on peut affecter des fonctions déjà existantes à ces constantes ou variables :
var stringAndIntToString: (String, Int) -> String
stringAndIntToString = shoppingList
stringAndIntToString("carrots", 3)
// => "You need to buy 3 carrots."
Comme pour les autres variables et constantes, la valeur que tu lui affectes doit être du bon type :
stringAndIntToString = printShoppingList
// Error: Cannot assign value of type '(String) -> ()' to type '(String, Int) -> String'
Comme les types de fonctions peuvent s'utiliser partout où d'autres types peuvent s'utiliser, il s'ensuit qu'ils peuvent servir de types de paramètres, être passés à d'autres fonctions et être appelés depuis ces fonctions.
func apply3(to str: String, function f: (String, Int) -> String) -> String {
f(str,3)
}
// apply3: ([String], (String, Int) -> String) -> [String]
apply3(to: "eggs", function: shoppingList)
// => "You need to buy 3 eggs."
apply3(to: "eggs", function: repeater)
// => "eggseggseggs"
De la même manière, les types de fonctions peuvent servir de types de retour pour des fonctions. Autrement dit, on peut écrire des fonctions qui créent et renvoient d'autres fonctions. Lorsqu'on crée ces fonctions, la fonction renvoyée peut utiliser les autres paramètres passés à la fonction ou les variables locales créées à l'intérieur de la fonction parente.
func makeAdder(base: Int) -> (Int) -> Int {
func adder(_ i: Int) -> Int {
base + i
}
return adder
}
// makeAdder: (Int) -> (Int) -> Int
let add10 = makeAdder(base: 10)
// add10: (Int) -> Int
let subtract20 = makeAdder(base: -20)
// subtract10: (Int) -> Int
add10(5)
// => 15
subtract20(5)
// => -15
Bonjour, Agent Double-Null0111.
Ta mission, si tu choisis de l'accepter, est d'écrire deux outils pour t'aider à infiltrer le quartier général d'UMBRA (United Minions Being Really Awful) et à récupérer les plans de leur dernière machination vraiment atroce. Deux outils te seront nécessaires pour mener à bien cette mission.
Une fois les plans secrets en ta possession, tu devras les protéger pour que seules les personnes qui connaissent le mot de passe puissent les récupérer.
Pour ce faire, tu devras implémenter la fonction protectSecret(_ secret: String, withPassword password: String) -> (String) -> String.
Cette fonction renvoie une autre fonction qui prend en entrée des strings pouvant être le mot de passe.
Si le mot de passe saisi est correct, la nouvelle fonction renvoie le secret dissimulé, mais si le mot de passe est incorrect, la fonction renvoie « Sorry. No hidden secrets here. »
let secretFunction = protectSecret("Steal the world's supply of french fries!", withPassword: "5up3r53cr37")
secretFunction("Open sesame")
// Returns "Sorry. No hidden secrets here."
secretFunction("5up3r53cr37")
// Returns "Steal the world's supply of french fries!"
Nous avons appris qu'UMBRA base toutes ses combinaisons de coffre-fort sur le numéro de la salle où se trouve le coffre. Ces combinaisons sont générées en appliquant de façon répétée une fonction spéciale au numéro de la salle. Ainsi, le premier nombre de la combinaison provient de l'application de la fonction au numéro de la salle, le deuxième de l'application de la fonction au premier nombre, et le troisième de l'application de la fonction au deuxième nombre.
Cependant, UMBRA change régulièrement la fonction utilisée pour générer les combinaisons, donc ton outil devra prendre à la fois un numéro de salle et la fonction appropriée pour générer la combinaison.
Implémente la fonction generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) pour générer la combinaison dont tu auras besoin.
func makeCombo(_ x: Int) -> Int {
(x * 13) % 256
}
generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
Inscris-toi sur Exercism pour apprendre et maîtriser Swift avec 35 concepts116 exercices, et un vrai mentorat humain, le tout gratuitement.