Lambda est une fonction anonyme représentée sous forme d'expression compacte { arguments -> corps }. En Kotlin, les lambdas sont le principal moyen de passer un comportement aux fonctions d'ordre supérieur, offrant une syntaxe concise sans avoir à déclarer une fonction séparée. Selon la documentation Kotlin (2026), plus de 70% des fonctions d'ordre supérieur dans les projets typiques sont appelées avec des lambdas. Lambda permet d'écrire du code dans un style fonctionnel avec un minimum de bruit syntaxique.
Points clés
Lambda (expression lambda) est une fonction anonyme définie comme une expression plutôt qu'une déclaration. Le terme provient du lambda-calcul d'Alonzo Church (1936). En programmation, une lambda est un bloc de code qui peut être passé comme valeur, stocké dans une variable et appelé ultérieurement. En Kotlin, une lambda est toujours entourée d'accolades { }, les arguments étant séparés du corps par la flèche ->.
Une lambda diffère d'une fonction classique par l'absence de nom et du mot-clé fun. Cela permet de déclarer le comportement directement au point d'utilisation, sans encombrer le code de déclarations supplémentaires. Le compilateur Kotlin infère les types des arguments à partir du contexte, donc dans de nombreux cas, les types peuvent être omis. Une lambda est un sucre syntaxique sur le type fonctionnel (T) -> R : chaque lambda a un type fonctionnel correspondant.
L'utilisation principale des lambdas en Kotlin est de les passer à des fonctions d'ordre supérieur. La bibliothèque standard utilise les lambdas partout : filter { it > 0 }, map { it.uppercase() }, forEach { println(it) }. Les lambdas sont également utilisées pour les écouteurs d'événements, les callbacks et les configurateurs d'objets via apply et run, rendant le code plus déclaratif par rapport aux classes anonymes.
La forme complète d'une expression lambda en Kotlin : { arguments -> corps_lambda }. Les arguments sont listés séparés par des virgules, suivis d'une flèche et du corps — une ou plusieurs expressions. Si le corps contient plusieurs lignes, la dernière expression devient la valeur de retour. Si une fonction accepte une lambda comme dernier argument, elle peut être placée en dehors des parenthèses d'appel.
val sum: (Int, Int) -> Int = { a, b -> a + b }
// Types déduits du contexte
val sumShort = { a: Int, b: Int -> a + b }
// Appel lambda
val result = sum(5, 3) // 8
println(result)
La variable sum est déclarée avec un type fonctionnel explicite (Int, Int) -> Int et initialisée avec une lambda { a, b -> a + b }. Pour sumShort, les types sont spécifiés à l'intérieur de la lambda et le type de la variable est inféré. Les deux variantes sont équivalentes. Appeler une lambda n'est pas différent d'appeler une fonction classique — en utilisant la syntaxe sum(5, 3). Une lambda sans arguments s'écrit { body }, avec un argument — { it -> it * 2 } ou simplement { it * 2 }.
Lorsqu'une lambda accepte exactement un argument, Kotlin fournit le nom implicite it. Cela élimine la nécessité de déclarer l'argument sur le côté gauche. Le développeur écrit uniquement le corps de la lambda, en utilisant it pour accéder au seul paramètre. Cette syntaxe est particulièrement pratique dans les chaînes de traitement de collections, où it fait référence à l'élément courant.
val numbers = listOf(1, 2, 3, 4, 5)
// Nom de paramètre explicite
val squaredExplicit = numbers.map { n -> n * n }
// it implicite
val squared = numbers.map { it * it }
// Filtrage avec it
val even = numbers.filter { it % 2 == 0 }
println(squared) // [1, 4, 9, 16, 25]
Dans l'exemple, map { it * it } utilise it au lieu de déclarer n ->. Kotlin attribue automatiquement it pour un paramètre lambda unique. Si une lambda accepte deux arguments ou plus, it n'est pas créé — tous les paramètres doivent être déclarés explicitement. Pour une meilleure lisibilité des lambdas imbriquées, il convient de donner des noms significatifs aux paramètres et d'utiliser it uniquement dans des prédicats courts d'une ligne.
Trailing lambda est une fonctionnalité syntaxique de Kotlin qui permet de déplacer le dernier argument lambda en dehors des parenthèses d'appel de la fonction. Cela fait ressembler le code à des constructions de langage intégrées. Si la lambda est le seul argument, les parenthèses peuvent être complètement omises. Cette approche est activement utilisée dans la bibliothèque standard et les DSL.
// Appel standard
thread(block = {
println("Bonjour depuis le thread")
})
// Version trailing lambda
thread {
println("Bonjour depuis le thread")
}
// repeat avec trailing lambda
repeat(3) { index ->
println("Itération $index")
}
// exécuter avec lambda multiligne
val config = run {
val host = "localhost"
val port = 8080
"$host:$port"
}
La fonction thread accepte un Runnable comme dernier argument. Grâce à la trailing lambda, la lambda peut être passée en dehors des parenthèses, ressemblant visuellement à un bloc de code. La fonction repeat prend un nombre d'itérations et une lambda avec un index. run est un exemple de fonction d'ordre supérieur où une lambda multiligne calcule une valeur retournée par la dernière expression. Les parenthèses autour de run() peuvent être omises si la lambda est le seul argument.
La capture de variables (closure) est la capacité d'une lambda à accéder aux variables déclarées dans la portée externe. En Kotlin, une lambda peut lire et modifier les variables var, ainsi que lire les variables val du contexte environnant. Les variables capturées sont stockées avec la lambda tout au long de son cycle de vie, permettant de créer des fonctions avec état.
fun makeCounter(): () -> Int {
var count = 0
return {
count++ // captures count
}
}
fun main() {
val counter = makeCounter()
println(counter()) // 0
println(counter()) // 1
println(counter()) // 2
}
La fonction makeCounter déclare une variable locale count et retourne une lambda { count++ }. Bien que makeCounter ait terminé son exécution, la lambda retournée conserve une référence à count via la fermeture. Chaque appel à counter() incrémente et retourne la valeur courante. Le mécanisme de closure sous-tend le currying, les fabriques de fonctions et la mémoïsation. Il est important de se rappeler que la capture de variables mutables peut entraîner un comportement inattendu en cas d'exécution concurrente.
Questions fréquentes
Lambda ne supporte pas le return inconditionnel — un return sans étiquette redonne le contrôle à la fonction externe. Pour quitter une lambda, utilisez return@label, où label est le nom de la fonction d'ordre supérieur à laquelle la lambda a été passée.
Une fonction anonyme s'écrit comme fun(a: Int): Int { return a * 2 } et supporte le return sans étiquette. Une lambda { a -> a * 2 } est plus courte en syntaxe mais nécessite return@label pour une sortie anticipée.
Si une lambda ne prend pas d'arguments, la flèche est omise : { body() }. Si elle prend un argument mais ne l'utilise pas, écrivez { _ -> body() } avec un tiret bas pour ignorer le paramètre.
Oui, chaque lambda passée à une fonction non inline crée une instance d'une classe anonyme. Pour les fonctions inline, la lambda est intégrée au site d'appel sans créer d'objet. Les lambdas sans capture sont mises en cache sous forme d'objets singleton.
Return en Kotlin est un opérateur de saut appartenant à la fonction la plus proche déclarée avec fun. Une lambda n'est pas une fonction (fun), mais une expression. Par conséquent, un return à l'intérieur d'une lambda sans étiquette est traité comme un retour de la fonction externe englobante.
Résumé
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.
Lisez aussi