Higher-order function : définition, caractéristiques et exemples en Kotlin

Auteur : IT Sectr Publié le : 2026-06-23 Temps de lecture : 8 min

Une higher-order function est une fonction qui prend une autre fonction comme paramètre ou retourne une fonction en résultat. En Kotlin, les fonctions sont des citoyens de première classe : elles peuvent être stockées dans des variables, passées comme arguments et retournées. Selon la documentation Kotlin (2026), les higher-order functions réduisent la duplication de code de 30% en moyenne par rapport aux approches impératives. Higher-order function est un concept fondamental du style fonctionnel dans le développement moderne.

Points clés

  • Higher-order function — fonction qui prend une autre fonction comme paramètre ou en retourne une
  • Type fonctionnel (T) -> R — la base pour déclarer des paramètres de fonction dans une signature
  • Expression lambda — moyen compact de passer une fonction à une higher-order function
  • Passage de comportement permet de paramétrer des opérations sans héritage ni interfaces
  • Retour de fonction depuis une higher-order function est utilisé pour les fabriques et les fermetures

Qu’est-ce qu’une higher-order function ?

Une higher-order function est une fonction qui possède au moins l’une des deux caractéristiques suivantes : prendre une autre fonction comme argument ou retourner une fonction comme résultat. En mathématiques, ces fonctions sont appelées fonctionnelles ou opérateurs. En programmation, elles sont apparues dans Lisp en 1958 et sont devenues une partie obligatoire de tous les langages modernes : JavaScript, Python, Swift, Kotlin, Scala et Haskell. Une higher-order function permet de s’abstraire d’une opération spécifique et de passer un comportement comme valeur.

La différence clé entre une higher-order function et une fonction ordinaire est la présence d’un paramètre avec un type fonctionnel ou d’une valeur fonctionnelle retournée. En Kotlin, un type fonctionnel s’écrit (ParamType) -> ReturnType. Par exemple, le type (Int) -> String signifie une fonction qui prend Int et retourne String. Le type () -> Unit dénote une fonction sans paramètres qui ne retourne aucune valeur utile. C’est ce système de types qui rend les higher-order functions type-safe.

L’opposé d’une higher-order function est une first-class function (fonction de première classe). First-class function signifie qu’une fonction peut être utilisée comme n’importe quelle autre valeur : assignée à une variable, stockée dans une collection, passée en argument. Une higher-order function est une fonction qui utilise des first-class functions pour accepter ou retourner. Kotlin prend en charge les deux concepts au niveau du langage sans bibliothèques supplémentaires.

Comment fonctionne une higher-order function en Kotlin ?

En Kotlin, toute fonction qui a au moins un paramètre déclaré avec un type fonctionnel ou dont le type de retour est fonctionnel est automatiquement considérée comme une higher-order function. Le compilateur ne nécessite pas d’annotation spéciale : il suffit de spécifier (T) -> R dans la signature. Lors de l’appel d’une telle fonction, l’argument est soit une expression lambda, soit une référence à une fonction existante via ::, soit une valeur fonctionnelle stockée dans une variable.

kotlin
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int {
    return op(a, b)
}

fun main() {
    val sum = operate(10, 20) { x, y -> x + y }
    println(sum) // 30
}

Dans le listing, la fonction operate prend deux entiers et un paramètre op de type (Int, Int) -> Int. Le corps de la fonction appelle l’opération passée en une seule ligne. Dans main, l’appel à operate passe le lambda { x, y -> x + y } — Kotlin le place après les parenthèses grâce à la syntaxe trailing lambda. Si le lambda était le dernier argument, il pourrait être complètement déplacé en dehors des parenthèses, ce qui améliore la lisibilité des chaînes d’appels.

Sous le capot, Kotlin compile les higher-order functions via l’interface Function (Function2 pour deux paramètres). Chaque lambda se transforme en une classe anonyme qui implémente l’interface FunctionN correspondante. Cela signifie que la création d’un lambda implique une allocation d’objet pour chaque opération. Pour réduire la surcharge, Kotlin prend en charge les fonctions inline, qui substituent le corps de la higher-order function au site d’appel, éliminant la création de la classe anonyme.

Fonctions comme paramètres : passage de comportement

Passer une fonction comme argument est le motif le plus courant d’utilisation des higher-order functions. Au lieu de créer une hiérarchie de classes avec une méthode polymorphe, le développeur passe le comportement souhaité directement au point d’utilisation. Cela implémente le principe Ouvert/Fermé sans héritage : une nouvelle opération est ajoutée comme un nouveau lambda, pas comme une nouvelle sous-classe.

Pour les fonctions nullables, Kotlin utilise le type ((T) -> R)? avec un point d’interrogation après les parenthèses. Une telle fonction ne peut être appelée qu’après une vérification de null ou via l’opérateur ?.invoke(). Dans ce cas, la signature de la higher-order function indique explicitement que passer une fonction est optionnel : le code appelant peut omettre l’argument. C’est utile pour les callbacks et les gestionnaires d’événements avec un comportement optionnel.

kotlin
fun <T> List<T>.customFilter(
    predicate: (T) -> Boolean
): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (predicate(item)) result.add(item)
    }
    return result
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val even = numbers.customFilter { it % 2 == 0 }
    println(even) // [2, 4]
}

La fonction d’extension customFilter prend un paramètre predicate de type fonctionnel (T) -> Boolean. À l’intérieur de la boucle, elle appelle predicate pour chaque élément et collecte ceux qui correspondent. L’appel dans main passe le lambda { it % 2 == 0 }, où it est le nom implicite du seul paramètre du lambda. Grâce aux higher-order functions, la logique de filtrage est complètement isolée du mécanisme de parcours de la collection.

Fonctions comme valeurs de retour

Une higher-order function peut retourner une fonction — ce motif est appelé fabrique de fonctions ou générateur de comportement. La fonction retournée peut capturer (closure) des variables de la portée externe, les préservant entre les appels. Cela permet de créer des gestionnaires configurables et des opérations spécialisées basés sur des modèles courants.

Lors du retour d’une fonction, Kotlin déduit le type fonctionnel ((T) -> R)? retourné à partir de la signature. Le compilateur vérifie que toutes les expressions return dans le corps retournent des valeurs fonctionnelles compatibles. Les variables capturées sont stockées dans l’objet lambda et restent accessibles tant qu’une référence existe. C’est un mécanisme puissant, mais qui nécessite une attention particulière à la gestion de la mémoire.

kotlin
fun makeMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

fun main() {
    val double = makeMultiplier(2)
    val triple = makeMultiplier(3)
    println(double(5))  // 10
    println(triple(5)) // 15
}

La fonction makeMultiplier prend un facteur et retourne un lambda { x -> x * factor }, où factor est capturé de la portée externe (closure). Chaque appel à makeMultiplier crée une nouvelle fonction avec sa propre valeur de factor. Les variables double et triple stockent les fonctions retournées et peuvent être appelées plusieurs fois. Ce motif est largement utilisé dans la configuration de clients HTTP, les décorateurs et les middleware.

Higher-order function avec lambdas : exemples

La combinaison de higher-order functions et de lambdas permet de construire des chaînes d’opérations expressives sans variables intermédiaires. La bibliothèque standard de Kotlin contient des dizaines de higher-order functions : let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy et d’autres. Chacune prend un lambda et effectue une transformation de données avec celui-ci.

kotlin
data class User(val name: String, val age: Int)

fun main() {
    val users = listOf(
        User("Alice", 25),
        User("Bob", 17),
        User("Charlie", 30)
    )

    val result = users
        .filter { it.age >= 18 }
        .map { it.name.uppercase() }
        .sorted()
    println(result) // [ALICE, CHARLIE]
}

Dans l’exemple, une chaîne de trois higher-order functions traite une liste d’utilisateurs. filter prend un prédicat, ne gardant que les adultes. map transforme chaque utilisateur en un nom en majuscules. sorted trie le résultat par ordre croissant. Chaque opération prend un lambda, et Kotlin assure la sécurité des types à chaque étape. Sans higher-order functions, il faudrait écrire une boucle avec if, des listes temporaires et un tri manuel.

Foire aux questions

En quoi une higher-order function diffère-t-elle d’une fonction ordinaire ?

Une higher-order function prend une autre fonction comme paramètre ou en retourne une. Une fonction ordinaire travaille uniquement avec des données : nombres, chaînes, objets. Une higher-order function travaille avec le comportement, passant la logique comme argument.

Une higher-order function peut-elle être inline ?

Oui, le modificateur inline élimine la surcharge de création d’une classe anonyme pour un lambda. En utilisant crossinline ou noinline, on peut contrôler quels lambdas sont substitués et lesquels restent des objets.

Quel est le type fonctionnel d’une fonction sans paramètres ?

Une fonction sans paramètres et sans valeur de retour a le type () -> Unit. Une fonction avec un paramètre de type T et un retour R s’écrit (T) -> R. Pour deux paramètres : (T, U) -> R, et ainsi de suite jusqu’à 22 arguments.

Quelle est la différence entre un lambda et une fonction anonyme ?

Un lambda est une notation concise { args -> body }, une fonction anonyme est fun(args): ReturnType { body }. Un lambda ne peut pas utiliser return sans étiquette, une fonction anonyme le peut. Les deux peuvent être passés à une higher-order function.

Quand éviter les higher-order functions ?

Évitez les higher-order functions dans les boucles critiques sans inline : chaque lambda crée un objet. Pour le code critique en performance, utilisez inline fun. N’abusez pas non plus des lambdas profondément imbriqués — cela réduit la lisibilité.

Résumé

  • Higher-order function — fonction qui prend une autre fonction comme paramètre ou en retourne une ; le fondement de la programmation fonctionnelle en Kotlin
  • Type fonctionnel (T) -> R déclare un paramètre de fonction avec une signature type-safe
  • Expression lambda — syntaxe compacte { args -> body } pour passer un comportement
  • Fonctions inline éliminent la surcharge de création de classes anonymes pour les lambdas
  • Fabriques de fonctions retournent une fonction avec un contexte capturé via le mécanisme de fermeture
  • Chaînes d’opérations filter-map-sorted sont construites sur des higher-order functions sans variables intermédiaires
  • Sécurité des types des higher-order functions est assurée par le système de types fonctionnels de Kotlin à la compilation

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi