La méthode manquante de la stdlib Dart : Iterable.intersperse()
En prenant du recul sur mon expérience avec Dart / Flutter, je constate l’ajout systématique d’une méthode dans chacun de mes projets : la méthode intersperse
. Cette fonction me permet d’insérer un élément spécifique entre chaque paire d’éléments d’un Iterable
. Bien que cette opération puisse sembler rudimentaire à première vue, elle facilite l’implémentation de certaines fonctionnalités (comme les espacements dans une Row
de l’image de couverture, par exemple). Permettez-moi donc, de vous faire découvrir cette méthode très utile.
La méthode intersperse()
Comme explicité dans l’introduction, nous allons implémenter la méthode intersperse
qui a pour objectif d’ajouter un intercalaire entre chaque paire d’éléments d’un Iterable
.
Iterable<T> intersperse<T>(T element, Iterable<T> iterable) sync* {
final iterator = iterable.iterator;
if (iterator.moveNext()) {
yield iterator.current;
while (iterator.moveNext()) {
yield element;
yield iterator.current;
}
}
}
La fonction intersperse
s’appuie sur l’interface Iterable
, ce qui lui permet de fonctionner de manière interchangeable avec toutes les collections qui implémentent cette interface (telles que List, Set, …).
La méthode intersperse
est ce que la documentation de Dart appelle un “Lazy Synchronous Generator”. En d’autres termes, la méthode ne traitera que ce qui lui est demandé, sans excéder, offrant ainsi des gains de performances en fonction du contexte d’utilisation.
Pour l’implémentation, nous nous basons sur l’Iterator
fourni par l’Iterable
, dont la fonction est de parcourir progressivement la liste source. À chaque itération, il suffit d’ajouter l’élément intercalaire (d’où le nom de la méthode), et le tour est joué.
La méthode d’extension
Etant d’avis que cette méthode devrait faire partie de la bibliothèque standard de Dart, j’apprécie l’implémenter sous la forme d’une méthode d’extension. Cependant, en fonction des conventions de votre équipe, il se peut que l’utilisation des méthodes d’extension soit interdite dans votre codebase (je ne suis pas là pour remettre cet éternel débat sur le tapis à vos pauses cafés). Ci-dessous, je vous propose un exemple pour l’intégrer en tant que méthode d’extension. A vous de voir en fonction des habitudes de votre équipe.
import './intersperse.dart' as core;
extension IntersperseExtensions<T> on Iterable<T> {
Iterable<T> intersperse(T element) {
return core.intersperse(element, this);
}
}
Exemple d’utilisation: ColumnWithGap
Column
et Row
ont maintenant un paramètre spacing
qui permet de faire exactement ce que nous cherchons à réaliser dans l’exemple ci-dessous. Je ne supprime néanmoins pas l’exemple car il y a d’autres usages possibles.
Afin de vous illustrer l’utilisation de cette méthode, je vous présente un exemple concret que j’ai implémenté dans plusieurs de mes projets : l’ajout de l’attribut gap
aux widgets Column
et Row
. Cela permet d’introduire un espacement entre les enfants, une fonctionnalité que l’on retrouve en CSS mais qui fait défaut dans Flutter. Il est temps de remédier à cela.
class ColumnWithGap extends Column {
final double gap;
ColumnWithGap({
super.key,
super.mainAxisAlignment,
super.mainAxisSize,
super.crossAxisAlignment,
super.textDirection,
super.verticalDirection,
super.textBaseline,
required List<Widget> children,
required this.gap,
}) : super(
children: intersperse(SizedBox(height: gap), children).toList(),
);
}
class RowWithGap extends Row {
final double gap;
RowWithGap({
super.key,
super.mainAxisAlignment,
super.mainAxisSize,
super.crossAxisAlignment,
super.textDirection,
super.verticalDirection,
super.textBaseline,
required List<Widget> children,
required this.gap,
}) : super(
children: intersperse(SizedBox(width: gap), children).toList(),
);
}
Comme vous pouvez le voir, l’ajout de la méthode intersperse
simplifie grandement l’implémentation de ses deux widgets. Il est assez facile d’imaginer d’autres usages.
A votre tour !
Cette méthode s’est avérée être précieuse dans l’ensemble de mes projets Flutter, et je suis sincèrement convaincu qu’elle mérite d’être intégrée à la bibliothèque standard, comme le suggère cette issue GitHub ouverte depuis septembre 2022 (Si vous aussi vous pensez que cette méthode devrait faire partie de la stdlib, n’hésitez pas à aller mettre un 👍 sur l’issue). Maintenant qu’elle est entre vos mains, je suis persuadé que vous trouverez de nombreuses autres applications auxquelles je n’avais pas encore pensé.