Je n'arrive pas à comprendre la raison à quoi sert d'ajouter cette fonctionnalité.
Méthode qui doit être passée en argument ou appelée par une autre méthode
func averageArg(_ plus: (Int, Int) -> Int, _ a: Int, _ b : Int) -> Int { return plus(a, b) / 2 }
lors de l'appel d'une fonction depuis une autre fonction
func average(_ a : Int, _ b : Int) -> Int{ return add(a, b) / 2 }
lors de la transmission d'une fonction comme argument à une autre fonction
func add(_ a : Int, _ b : Int) -> Int { return a + b }
4 Réponses :
Par exemple, sans la fonction "postProcess" comme argument, vous devrez implémenter des fonctions d'arborescence: getAndAddData, getAndSubData et getAndMulData.
func add(_ a:Int, _ b:Int) -> Int { return a + b } func sub(_ a:Int, _ b:Int) -> Int{ return a - b } func mul(_ a:Int, _ b:Int) -> Int{ return a * b } func getAndProcessData(_ postProcess:(Int, Int) -> Int, _ a:Int, _ b:Int) -> Int { let a2 = ExampleClass.get(a) let b2 = ExampleClass.get(b) return postProcess(a2, b2) } func exampleFunc(a:Int, b:Int) { let getAndAdd = self.getAndProcessData(self.add(_:_:), a, b) let getAndSub = self.getAndProcessData(self.sub(_:_:), a, b) let getAndMul = self.getAndProcessData(self.mul(_:_:), a, b) }
La raison de prendre une fonction comme argument est qu'elle rend votre fonction plus flexible. Il permet à appelant de décider ce que fait Par exemple, supposons que l'appelant souhaite que ou prenez le Un meilleur exemple de ceci est la fonction Swift Voici un exemple utilisant une fonction: L'auteur de plus
en passant une fonction ou une fermeture qui combine deux valeurs Int
pour renvoyer un code Int > valeur.
plus
multiplie les valeurs: ["Ed", "Jo", "Bob", "Bill", "Chuck", "Alexander"]
func shortNamesFirst(_ name1: String, _ name2: String) -> Bool {
if name1.count < name2.count {
return true
} else if name1.count > name2.count {
return false
} else {
// when names are the same length, sort
// them alphabetically
return name1 < name2
}
}
["Chuck", "Bob", "Bill", "Jo", "Ed", "Alexander"].sorted(by: shortNamesFirst)
max
des deux valeurs (en passant une fermeture): [4, 3, 2, 1]
[1, 3, 2, 4].sorted(by: >)
trié (par :)
. sorted
prend une fermeture qui détermine ce que signifie areInIncreasingOrder
. Cela vous permet de trier un tableau par ordre croissant et décroissant en changeant simplement la fonction passée: [1, 2, 3, 4]
[1, 3, 2, 4].sorted(by: <)
50
print(averageArg({ max($0, $1) }, 1, 100))
15
print(averageArg(*, 5, 6))
sorted
n'a pas à fournir une version différente de sorted
pour chaque type de commande qu'un utilisateur peut souhaiter. L'utilisateur décide de ce que signifie pour lui trié
.
Donc, l'avantage est donc: Différentes fonctions avec des fonctionnalités différentes pourraient être passées tant qu'elle a la même structure définie dans le paramètre de la fonction d'appel, qui est restreinte lorsque nous appelons une fonction par son nom dans une autre fonction.
D'accord. Merci. Cela a été utile. :)
Votre exemple n'est pas une utilisation très convaincante du passage des fermetures. Cependant, imaginez que la mise en œuvre est variable, c'est à dire. vous ne savez pas ce qui devrait arriver dans certaines circonstances, la manipulation des fermetures est un grand avantage. Prenons cet exemple:
func doSomethingAsynchronously(completion completionClosure: (() -> Void)? = nil) { // Do asynchronous stuff if let completionClosure = completionClosure { completionClosure() } }
Cela permet à un appelant de doSomething
mais de gérer les échecs de la fonction de manière personnalisée en passant une fermeture.
Cela devient vraiment utile dans les situations asynchrones, où le résultat de votre fonction est utilisé pour faire quelque chose mais vous ne pouvez pas exécuter l'exécution dans le même thread (par exemple, les appels réseau).
func doSomething(with: AnyObject, whenFails failureClosure: ((Error) -> Void)? = nil) { var error: Error? // do stuff, maybe setting the error to something... if let error = error, let failureClosure = failureClosure { failureClosure(error) } }
C'est une fonctionnalité de swift qui n'est pas souvent utilisée, mais qui peut parfois s'avérer extrêmement utile. Dans votre exemple, cela n'aurait en effet pas de sens, mais trouvons un scénario dans lequel cela a réellement du sens.
Voyons d'abord ce que signifie _ plus: (Int, Int) -> Int
. Ce morceau de code signifie que votre fonction averageArg
accepte toute fermeture ou fonction qui prend deux paramètres entiers et fournit un entier en sortie. Comme add (...)
est conforme à cette exigence (deux arguments integer
et il donne un integer
en sortie), vous pouvez le transmettre comme argument.
Mais regardons un exemple où un tel paramètre aurait du sens. Disons que nous écrivons un code frontal pour une application qui affiche des avis sur les hôtels. Dans cette application, nous devons écrire quelque part une fonction fetchReviews (_ serverResponse: ([Review]) -> Void)
qui obtient tous les avis sur les hôtels d'un serveur distant:
struct Review { let author: String let rating: Int } func fetchReviews(_ completionHandler: @escaping ([Review]) -> Void) { // Lets do a request to the server on a separate thread, so that the user can keep // interacting with the app. The app doesn't freeze. // Making qos .userInitiated will ensure that user interaction will be more important than // our backend request. DispatchQueue.global(qos: .userInitiated).async { // Do some request to the server.... //... // Lets pretend we have received a response, and we are turning the response into an array of reviews completionHandler([Review]()) } }
Comme il peut y avoir un délai (parfois long) entre le moment où le serveur répond et donne tous les avis, et entre le moment où fetchReviews
a été appelé, ce ne serait pas bien pour l'utilisateur si l'application se fige simplement. Au lieu de cela, vous pouvez faire la demande au serveur sur un thread distinct afin que l'utilisateur puisse continuer à utiliser l'application et que l'application ne se fige pas (voir la partie DispatchQueue.global
).
Cependant, nous voulons toujours afficher tous les avis à l'utilisateur une fois que nous recevons une réponse du serveur. En ajoutant le paramètre _ serverResponse
, nous pouvons avertir quiconque a appelé fetchReviews
dès que nous avons effectivement reçu la réponse du serveur. En procédant ainsi, l'utilisateur peut continuer à interagir avec l'application, et une fois que les avis sont disponibles, nous pouvons les montrer à l'utilisateur!
Pouvez-vous nous donner un peu de contexte? Où ce code est-il utilisé et dans quel but?
Ce code n'est qu'un exemple. Je parcourais la documentation de Swift et suis tombé sur ce concept de «type de fonction en tant que paramètre».