Voici une liste des principales mises à jour de cette version :
- Le nouveau compilateur Kotlin К2 est maintenant en Alpha et offre de sérieuses améliorations de performances. Il n'est disponible que pour la JVM et aucun des plugins du compilateur, y compris kapt, ne fonctionne avec.
- Une nouvelle approche de la compilation incrémentale dans Gradle. La compilation incrémentielle est désormais également prise en charge pour les modifications apportées à l'intérieur des modules non-Kotlin dépendants et est compatible avec Gradle.
- JetBrains a stabilisé les annotations d'exigence d'acceptation, les types définitivement non nullables et l'inférence du constructeur.
- Il existe maintenant un opérateur de soulignement pour les arguments de type. Vous pouvez l'utiliser pour déduire automatiquement un type d'argument lorsque d'autres types sont spécifiés.
- Cette version permet la mise en œuvre par délégation à une valeur en ligne d'une classe en ligne. Vous pouvez désormais créer des wrappers légers qui n'allouent pas de mémoire dans la plupart des cas.
Nouveau compilateur Kotlin K2 pour la JVM en Alpha
Cette version de Kotlin présente la version Alpha du nouveau compilateur Kotlin K2. Le nouveau compilateur vise à accélérer le développement de nouvelles fonctionnalités de langage, à unifier toutes les plateformes prises en charge par Kotlin, à apporter des améliorations de performances et à fournir une API pour les extensions de compilateur.
JetBrains indique qu'il est important de souligner qu'avec la version Alpha du nouveau compilateur K2, l'éditeur s'est principalement concentré sur l'amélioration des performances. C'est la raison pour laquelle, pour le moment, ce nouveau compilateur ne fonctionne qu'avec les projets JVM : il ne prend pas en charge Kotlin/JS, Kotlin/Native ou d'autres projets multiplateformes, et aucun des plugins de compilateur, y compris kapt, ne fonctionne avec lui.
Les benchmarks de JetBrains montrent des résultats remarquables sur ses projets internes :
Les chiffres de performance KLOC/s représentent le nombre de milliers de lignes de code que le compilateur traite par seconde.
Langage
Kotlin 1.7.0 introduit la prise en charge de l'implémentation par délégation et un nouvel opérateur de soulignement pour les arguments de type. Il stabilise également plusieurs fonctionnalités de langage introduites en tant que préversions dans les versions précédentes.
Autoriser l'implémentation par délégation à une valeur inline d'une classe inline
Si vous souhaitez créer un wrapper léger pour une instance de valeur ou de classe, il est nécessaire d'implémenter toutes les méthodes d'interface à la main. L'implémentation par délégation résout ce problème, mais elle ne fonctionnait pas avec les classes inline avant la version 1.7.0. Cette restriction a été supprimée, vous pouvez donc désormais créer des wrappers légers qui n'allouent pas de mémoire dans la plupart des cas.
Code kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | interface Bar { fun foo() = "foo" } @JvmInline value class BarWrapper(val bar: Bar): Bar by bar fun main() { val bw = BarWrapper(object: Bar {}) println(bw.foo()) } |
Opérateur de soulignement pour les arguments de type
Kotlin 1.7.0 introduit un opérateur de soulignement, _, pour les arguments de type. Vous pouvez l'utiliser pour déduire automatiquement un argument de type lorsque d'autres types sont spécifiés :
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | abstract class SomeClass<T> { abstract fun execute(): T } class SomeImplementation : SomeClass<String>() { override fun execute(): String = "Test" } class OtherImplementation : SomeClass<Int>() { override fun execute(): Int = 42 } object Runner { inline fun <reified S: SomeClass<T>, T> run(): T { return S::class.java.getDeclaredConstructor().newInstance().execute() } } fun main() { // T is inferred as String because SomeImplementation derives from SomeClass<String> val s = Runner.run<SomeImplementation, _>() assert(s == "Test") // T is inferred as Int because OtherImplementation derives from SomeClass<Int> val n = Runner.run<OtherImplementation, _>() assert(n == 42) } |
Vous pouvez utiliser l'opérateur de soulignement à n'importe quelle position dans la liste des variables pour déduire un argument de type.
Inférence de constructeur stable
L'inférence de générateur est un type spécial d'inférence de type qui est utile lors de l'appel de fonctions de générateur génériques. Il aide le compilateur à déduire les arguments de type d'un appel en utilisant les informations de type sur les autres appels à l'intérieur de son argument lambda.
À partir de la version 1.7.0, l'inférence de générateur est automatiquement activée si une inférence de type standard ne peut pas obtenir suffisamment d'informations sur un type sans spécifier l'option de compilateur -Xenable-builder-inference, qui a été introduite dans la version 1.6.0.
Conditions d'adhésion (opt-in) stables
Les conditions d'adhésion sont désormais stables et ne nécessitent pas de configuration supplémentaire du compilateur.
Avant la version 1.7.0, la fonctionnalité opt-in elle-même nécessitait l'argument -opt-in=kotlin.RequiresOptIn pour éviter un avertissement. Cela n'est plus nécessaire ; cependant, vous pouvez toujours utiliser l'argument du compilateur -opt-in pour accepter d'autres annotations, module par module.
Types stables définitivement non nullables
Dans Kotlin 1.7.0, les types définitivement non nullables ont été promus à Stable. Ils offrent une meilleure interopérabilité lors de l'extension des classes et des interfaces Java génériques.
Vous pouvez marquer un paramètre de type générique comme définitivement non nullable sur le site d'utilisation avec la nouvelle syntaxe T & Any. La forme syntaxique provient de la notation des types d'intersection et est maintenant limitée à un paramètre de type avec des bornes supérieures nullables sur le côté gauche de & et un Any non nullable sur le côté droit :
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y fun main() { // OK elvisLike<String>("", "").length // Error: 'null' cannot be a value of a non-null type elvisLike<String>("", null).length // OK elvisLike<String?>(null, "").length // Error: 'null' cannot be a value of a non-null type elvisLike<String?>(null, null).length } |
Kotlin/JVM
Cette version apporte des améliorations de performances pour le compilateur Kotlin/JVM et une nouvelle option de compilateur. De plus, les références appelables aux constructeurs d'interfaces fonctionnelles sont devenues stables. Notez que depuis la 1.7.0, la version cible par défaut pour les compilations Kotlin/JVM est désormais la 1.8.
Optimisations des performances du compilateur
Kotlin 1.7.0 introduit des améliorations de performances pour le compilateur Kotlin/JVM. Selon les benchmarks de JetBrains, le temps de compilation a été réduit de 10% en moyenne par rapport à Kotlin 1.6.0. Les projets avec de nombreuses utilisations de fonctions en ligne, par exemple, les projets utilisant kotlinx.html, seront compilés plus rapidement grâce aux améliorations apportées au post-traitement du bytecode.
Nouvelle option du compilateur : -Xjdk-release
Kotlin 1.7.0 présente une nouvelle option de compilateur, -Xjdk-release. Cette option est similaire à l'option de ligne de commande --release de javac. L'option -Xjdk-release contrôle la version cible du bytecode et limite l'API du JDK dans le classpath à la version Java spécifiée. Par exemple, kotlinc -Xjdk-release=1.8 n'autorisera pas le référencement de java.lang.Module même si le JDK dans les dépendances est la version 9 ou supérieure.
Kotlin/natif
Kotlin 1.7.0 inclut des modifications de l'interopérabilité Objective-C et Swift et stabilise les fonctionnalités introduites dans les versions précédentes. Il apporte également des améliorations de performances pour le nouveau gestionnaire de mémoire ainsi que d'autres mises à jour.
Améliorations des performances pour le nouveau gestionnaire de mémoire
Le nouveau gestionnaire de mémoire est toujours en Alpha, mais il est en passe de devenir Stable. Cette version offre des améliorations de performances significatives pour le nouveau gestionnaire de mémoire, en particulier dans la récupération de place (GC). En particulier, l'implémentation simultanée de la phase de balayage, introduite dans la version 1.6.20, est désormais activée par défaut. Cela permet de réduire le temps de pause de l'application pour GC. Le nouveau planificateur GC est meilleur pour choisir la fréquence GC, en particulier pour les tas plus importants.
De plus, JetBrains a spécifiquement optimisé les binaires de débogage, en veillant à ce que le niveau d'optimisation et les optimisations de temps de liaison appropriés soient utilisés dans le code d'implémentation du gestionnaire de mémoire. Cela leur a permis d'améliorer le temps d'exécution d'environ 30 % pour les binaires de débogage sur nos benchmarks.
Plug-in de compilateur unifié ABI avec backends JVM et JS IR
À partir de Kotlin 1.7.0, le plug-in Kotlin Multiplatform Gradle utilise le fichier jar de compilateur intégrable pour Kotlin/Native par défaut. Cette fonctionnalité a été annoncée dans la version 1.6.0 comme expérimentale, et maintenant elle est stable et prête à l'emploi. Cette amélioration est très pratique pour les auteurs de bibliothèques, car elle améliore l'expérience de développement du plugin du compilateur. Avant cette version, vous deviez fournir des artefacts distincts pour Kotlin/Native, mais vous pouvez désormais utiliser les mêmes artefacts de plug-in de compilateur pour Native et les autres plateformes prises en charge.
Prise en charge des exécutables Android autonomes
Kotlin 1.7.0 fournit une prise en charge complète de la génération d'exécutables standard pour les cibles Android natives. Il a été introduit dans 1.6.20, et maintenant il est activé par défaut. Si vous souhaitez revenir au comportement précédent lorsque Kotlin/Native a généré des bibliothèques partagées, utilisez le paramètre suivant :
Code Kotlin : | Sélectionner tout |
binaryOptions["androidProgramType"] = "nativeActivity"
Interopérabilité avec Swift async/wait : renvoi de Void au lieu de KotlinUnit
Les fonctions suspend de Kotlin renvoient désormais le type Void au lieu de KotlinUnit dans Swift. Ceci est le résultat de l'amélioration de l'interopérabilité avec l'async/wait de Swift. Cette fonctionnalité a été introduite dans la version 1.6.20 et cette version active ce comportement par défaut.
Vous n'avez pas besoin d'utiliser la propriété kotlin.native.binary.unitSuspendFunctionObjCExport=proper pour retourner le type approprié pour de telles fonctions.
Exceptions non déclarées interdites via les ponts Objective-C
Lorsque vous appelez du code Kotlin à partir du code Swift/Objective-C (ou vice versa) et que ce code lève une exception, il doit être géré par le code où l'exception s'est produite, sauf si vous avez spécifiquement autorisé le transfert d'exceptions entre les langages avec une conversion appropriée (par exemple, en utilisant l'annotation @Throws).
Auparavant, Kotlin avait un autre comportement involontaire où des exceptions non déclarées pouvaient "fuir" d'un langage à un autre dans certains cas. Kotlin 1.7.0 corrige ce problème, et maintenant de tels cas conduisent à l'arrêt du programme.
Ainsi, par exemple, si vous avez un lambda { throw Exception() } dans Kotlin et que vous l'appelez depuis Swift, dans Kotlin 1.7.0, il se terminera dès que l'exception atteindra le code Swift. Dans les versions précédentes de Kotlin, une telle exception pouvait fuir vers le code Swift.
Intégration améliorée de CocoaPods
À partir de Kotlin 1.7.0, vous n'avez plus besoin d'installer le plugin Cocoapods-generate si vous souhaitez intégrer CocoaPods dans vos projets.
Auparavant, vous deviez installer à la fois le gestionnaire de dépendances CocoaPods et le plug-in de génération de cocoapods pour utiliser CocoaPods, par exemple, pour gérer les dépendances iOS dans les projets Kotlin Multiplatform Mobile.
Désormais, la configuration de l'intégration de CocoaPods est plus facile et JetBrains a résolu le problème où Cocoapods-generate ne pouvait pas être installé sur Ruby 3 et versions ultérieures. Désormais, les dernières versions de Ruby qui fonctionnent mieux sur Apple M1 sont également prises en charge.
Remplacement de l'URL de téléchargement du compilateur Kotlin/Native
À partir de Kotlin 1.7.0, vous pouvez personnaliser l'URL de téléchargement du compilateur Kotlin/Native. Ceci est utile lorsque les liens externes sur le CI sont interdits. Pour remplacer l'URL de base par défaut https://download.jetbrains.com/kotlin/native/builds, utilisez la propriété Gradle suivante :
Code Kotlin : | Sélectionner tout |
kotlin.native.distribution.baseDownloadUrl=https://example.com
Kotlin/JS
Kotlin/JS reçoit de nouvelles améliorations au backend du compilateur JS IR avec d'autres mises à jour qui peuvent faire de votre expérience de développement.
Améliorations des performances pour le nouveau backend IR
Cette version a des mises à jour majeures qui devraient améliorer votre expérience de développement:
- Les performances de compilation incrémentale de Kotlin / JS ont été considérablement améliorées. Il faut moins de temps pour construire vos projets JS. Les reconstructions incrémentielles devraient désormais être à peu près à égalité avec le backend hérité dans de nombreux cas maintenant.
- Le paquet final Kotlin / JS nécessite moins d'espace, car nous avons considérablement réduit la taille des artefacts finaux. Nous avons mesuré jusqu'à une réduction de 20% de la taille du bundle de production par rapport au backend hérité pour certains grands projets.
- Le type de vérification des interfaces a été amélioré par les ordres de grandeur.
- Kotlin génère du code JS de meilleure qualité
Minification pour les noms des membres lorsque vous utilisez IR
Le compilateur Kotlin/JS IR utilise désormais ses informations internes sur les relations de vos classes et fonctions Kotlin pour appliquer une minification plus efficace, raccourcissant les noms des fonctions, des propriétés et des classes. Cela rétrécit les applications groupées résultantes.
Ce type de minification est automatiquement appliqué lorsque vous créez votre application Kotlin / JS en mode de production et est activé par défaut. Pour désactiver la minification du nom du membre, utilisez l'indicateur -Xir-minimized-member-names:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 | kotlin { js(IR) { compilations.all { compileKotlinTask.kotlinOptions.freeCompilerArgs += listOf("-Xir-minimized-member-names=false") } } } |
Prise en charge des navigateurs plus âgés via des polyfills dans le backend IR
Le backend du compilateur IR pour Kotlin / JS comprend désormais les mêmes polyfills que le backend hérité. Cela permet au code compilé avec le nouveau compilateur d'exécuter dans des navigateurs plus anciens qui ne prennent pas en charge toutes les méthodes d'ES2015 utilisées par la bibliothèque standard Kotlin. Seuls les polyfills réellement utilisés par le projet sont inclus dans le pack final, ce qui minimise leur impact potentiel sur la taille du bundle.
Cette fonctionnalité est activée par défaut lorsque vous utilisez le compilateur IR, et vous n'avez pas besoin de le configurer.
Chargez dynamiquement les modules JavaScript des expressions JS
Lorsque vous travaillez avec les modules JavaScript, la plupart des applications utilisent des importations statiques, dont l'utilisation est couverte par l'intégration du module JavaScript. Cependant, Kotlin / JS ne disposait pas d'un mécanisme pour charger dynamiquement les modules JavaScript au moment de l'exécution dans vos applications.
À partir de Kotlin 1.7.0, l'instruction d'importation de JavaScript est prise en charge en blocs JS, vous permettant d'apporter dynamiquement des packages dans votre application lors de l'exécution:
Code Kotlin : | Sélectionner tout |
val myPackage = js("import('my-package')")
Spécifiez les variables d'environnement pour les coureurs de test JavaScript
Pour régler la résolution de package Node.js ou passer des informations externes aux tests Node.js, vous pouvez désormais spécifier les variables d'environnement utilisées par les coureurs de test JavaScript. Pour définir une variable d'environnement, utilisez la fonction Environment() avec une paire de valeurs clés à l'intérieur du bloc TestTask dans votre script de construction:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | kotlin { js { nodejs { testTask { environment("key", "value") } } } } |
Bibliothèque standard
Dans Kotlin 1.7.0, la bibliothèque standard a reçu une gamme de modifications et d'améliorations. Ils introduisent de nouvelles fonctionnalités, stabilisent les expérimentales et unifient le soutien pour les groupes de capture nommés pour natifs, JS et JVM:
- Les fonctions de collection min () et max () reviennent comme non nullables
- Expression régulière correspondant à des indices spécifiques
- Support prolongé des versions de langue et d'API précédentes
- Accès aux annotations via la réflexion
- Fonctions récursives profondes stables
- Marques de temps basées sur les classes en ligne pour la source de temps par défaut
- Nouvelles fonctions d'extension expérimentales pour les options Java
- Support pour les groupes de capture nommés en JS et natif
Les fonctions de collection min() et max() retournées comme non nullable
Dans Kotlin 1.4.0, JetBrains a renommé les fonctions de collection min() et max() en minOrNull() et maxOrNull(). Ces nouveaux noms reflètent mieux leur comportement - renvoyant null si la collection du récepteur est vide. Cela a également permis d'aligner le comportement des fonctions sur les conventions de dénomination utilisées dans l'API des collections Kotlin.
Il en était de même pour minBy(), maxBy(), minWith() et maxWith(), qui ont tous obtenu leurs synonymes *OrNull() dans Kotlin 1.4.0. Les fonctions plus anciennes affectées par ce changement ont été progressivement obsolètes.
Kotlin 1.7.0 réintroduit les noms de fonction d'origine, mais avec un type de retour non nullable. Les nouvelles fonctions min(), max(), minBy(), maxBy(), minWith() et maxWith() renvoient désormais strictement l'élément de collection ou lèvent une exception.
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 | fun main() { val numbers = listOf<Int>() println(numbers.maxOrNull()) // "null" println(numbers.max()) // "Exception in... Collection is empty." } |
Correspondance d'expressions régulières à des indices spécifiques
Les fonctions Regex.matchAt() et Regex.matchesAt(), introduites dans la version 1.5.30, sont désormais stables. Elles fournissent un moyen de vérifier si une expression régulière a une correspondance exacte à une position particulière dans une String ou une CharSequence.
matchesAt() recherche une correspondance et renvoie un résultat booléen*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 | fun main() { val releaseText = "Kotlin 1.7.0 is on its way!" // regular expression: one digit, dot, one digit, dot, one or more digits val versionRegex = "\\d[.]\\d[.]\\d+".toRegex() println(versionRegex.matchesAt(releaseText, 0)) // "false" println(versionRegex.matchesAt(releaseText, 7)) // "true" } |
matchAt() renvoie la correspondance si elle est trouvée, ou null si elle ne l'est pas*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 | fun main() { val releaseText = "Kotlin 1.7.0 is on its way!" val versionRegex = "\\d[.]\\d[.]\\d+".toRegex() println(versionRegex.matchAt(releaseText, 0)) // "null" println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0" } |
Prise en charge étendue des versions de langage et d'API précédents
Pour aider les auteurs de bibliothèques à développer des bibliothèques destinées à être consommables dans un large éventail de versions précédentes de Kotlin, et pour faire face à la fréquence accrue des principales versions de Kotlin, JetBrains a étendu sa prise en charge des versions de langage et d'API précédents.
Avec Kotlin 1.7.0, JetBrains prend en charge trois versions de langage et d'API précédents au lieu de deux. Cela signifie que Kotlin 1.7.0 prend en charge le développement de bibliothèques ciblant les versions de Kotlin jusqu'à 1.4.0.
Accès aux annotations par réflexion
La fonction d'extension KAnnotatedElement.findAnnotations(), qui a été introduite pour la première fois dans la version 1.6.0, est désormais stable. Cette fonction de réflexion renvoie toutes les annotations d'un type donné sur un élément, y compris les annotations appliquées individuellement et répétées.
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Repeatable annotation class Tag(val name: String) @Tag("First Tag") @Tag("Second Tag") fun taggedFunction() { println("I'm a tagged function!") } fun main() { val x = ::taggedFunction val foo = x as KAnnotatedElement println(foo.findAnnotations<Tag>()) // [@Tag(name=First Tag), @Tag(name=Second Tag)] } |
Fonctions récursives profondes stables
Les fonctions récursives profondes sont disponibles en tant que fonctionnalité expérimentale depuis Kotlin 1.4.0, et elles sont maintenant stables dans Kotlin 1.7.0. À l'aide de DeepRecursiveFunction, vous pouvez définir une fonction qui conserve sa pile sur le tas au lieu d'utiliser la pile d'appels réelle. Cela vous permet d'exécuter des calculs récursifs très approfondis. Pour appeler une fonction récursive profonde, invoquez-la.
Dans cet exemple, une fonction récursive profonde est utilisée pour calculer la profondeur d'un arbre binaire de manière récursive. Même si cet exemple de fonction s'appelle de manière récursive 100*000*fois, aucune erreur StackOverflowError n'est générée*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Tree(val left: Tree?, val right: Tree?) val calculateDepth = DeepRecursiveFunction<Tree?, Int> { t -> if (t == null) 0 else maxOf( callRecursive(t.left), callRecursive(t.right) ) + 1 } fun main() { // Generate a tree with a depth of 100_000 val deepTree = generateSequence(Tree(null, null)) { prev -> Tree(prev, null) }.take(100_000).last() println(calculateDepth(deepTree)) // 100000 } |
Envisagez d'utiliser des fonctions récursives profondes dans votre code lorsque votre profondeur de récursivité dépasse 1 000 appels.
Marques de temps basées sur des classes en ligne pour la source de temps par défaut
Kotlin 1.7.0 améliore les performances de la fonctionnalité de mesure du temps en modifiant les repères temporels renvoyés par TimeSource.Monotonic en classes de valeurs en ligne. Cela signifie que l'appel de fonctions telles que markNow(), elapsedNow(), measureTime() et measureTimedValue() n'alloue pas de classes wrapper pour leurs instances TimeMark. En particulier lors de la mesure d'un morceau de code faisant partie d'un chemin à chaud, cela peut aider à minimiser l'impact de la mesure sur les performances*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 | @OptIn(ExperimentalTime::class) fun main() { val mark = TimeSource.Monotonic.markNow() // Returned `TimeMark` is inline class val elapsedDuration = mark.elapsedNow() } |
Nouvelles fonctions d'extension expérimentales pour Java Optionals
Kotlin 1.7.0 est livré avec de nouvelles fonctions pratiques qui simplifient le travail avec les classes facultatives en Java. Ces nouvelles fonctions peuvent être utilisées pour déballer et convertir des objets facultatifs sur la JVM et aider à rendre le travail avec les API Java plus concis.
Les fonctions d'extension getOrNull(), getOrDefault() et getOrElse() vous permettent d'obtenir la valeur d'un Optional s'il est présent. Sinon, vous obtenez une valeur par défaut, null, ou une valeur renvoyée par une fonction, respectivement*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | val presentOptional = Optional.of("I'm here!") println(presentOptional.getOrNull()) // "I'm here!" val absentOptional = Optional.empty<String>() println(absentOptional.getOrNull()) // null println(absentOptional.getOrDefault("Nobody here!")) // "Nobody here!" println(absentOptional.getOrElse { println("Optional was absent!") "Default value!" }) // "Optional was absent!" // "Default value!" |
Les fonctions d'extension toList(), toSet() et asSequence() convertissent la valeur d'un Optional présent en une liste, un ensemble ou une séquence, ou renvoient une collection vide dans le cas contraire. La fonction d'extension toCollection() ajoute la valeur Optional à une collection de destination déjà existante*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | val presentOptional = Optional.of("I'm here!") val absentOptional = Optional.empty<String>() println(presentOptional.toList() + "," + absentOptional.toList()) // ["I'm here!"], [] println(presentOptional.toSet() + "," + absentOptional.toSet()) // ["I'm here!"], [] val myCollection = mutableListOf<String>() absentOptional.toCollection(myCollection) println(myCollection) // [] presentOptional.toCollection(myCollection) println(myCollection) // ["I'm here!"] val list = listOf(presentOptional, absentOptional).flatMap { it.asSequence() } println(list) // ["I'm here!"] |
Ces fonctions d'extension sont introduites en tant qu'expérimentales dans Kotlin 1.7.0.
Prise en charge des groupes de capture nommés dans JS et Native
À partir de Kotlin 1.7.0, les groupes de capture nommés sont pris en charge non seulement sur la JVM, mais également sur les plates-formes JS et natives.
Pour donner un nom à un groupe de capture, utilisez la syntaxe (?<nom>groupe) dans votre expression régulière. Pour obtenir le texte correspondant à un groupe, appelez la nouvelle fonction MatchGroupCollection.get() et transmettez le nom du groupe.
Récupérer la valeur de groupe correspondante par nom
Considérez cet exemple pour faire correspondre les coordonnées de la ville. Pour obtenir une collection de groupes correspondant à l'expression régulière, utilisez groups. Comparez la récupération du contenu d'un groupe par son numéro (index) et par son nom en utilisant value*:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 | fun main() { val regex = "\\b(?<city>[A-Za-z\\s]+),\\s(?<state>[A-Z]{2}):\\s(?<areaCode>[0-9]{3})\\b".toRegex() val input = "Coordinates: Austin, TX: 123" val match = regex.find(input)!! println(match.groups["city"]?.value) // "Austin" by name println(match.groups[2]?.value) // "TX" by number } |
En savoir plus sur Kotlin 1.7.0