J'ai récemment eu davantage de temps pour écrire du code en Zig, et cela m'a fait du bien. Cet article partage des réflexions sur les abstractions en Zig, y compris des techniques que l'auteur a trouvées utiles mais rarement employées plus largement.
Beaucoup a été écrit sur les interfaces de Zig, et à juste titre. Bien que les interfaces ne soient pas une fonctionnalité du langage, elles constituent la manière de facto d'implémenter le polymorphisme à l'exécution en Zig. On a aussi beaucoup parlé de comptime en Zig et de la manière de l'exploiter pour éviter les problèmes de performance de la répartition dynamique et écrire un code élégant et orienté données.
Le polymorphisme en Zig s'obtient traditionnellement de deux façons. Les interfaces dynamiques utilisent des pointeurs opaques, des tables virtuelles et la répartition dynamique pour réaliser un polymorphisme à l'exécution. Le duck typing à la compilation utilise la réflexion sur les types, les instructions switch et la monomorphisation à la compilation pour réaliser un polymorphisme statique. Cette situation s'est révélée efficace, mais elle n'est pas sans compromis. Les interfaces offrent des contrats de types familiers d'autres langages, mais comme elles sont modulaires à l'exécution, elles constituent une barrière stricte pour le compilateur et entraînent donc un surcoût de performance. Pour le code critique en performance, Zig s'appuie généralement sur le duck typing à la compilation, qui détecte les violations d'interface à la compilation mais exige néanmoins une documentation soigneuse du contrat.
Les développeurs venant des traits de Rust ou des typeclasses de Haskell pourraient trouver cet arrangement simpliste, et Zig vise effectivement la simplicité. L'auteur soutient qu'avec un peu d'adaptation, des abstractions similaires sur les types sont possibles dans l'espace utilisateur de Zig. La proposition est une nouvelle convention pour définir des contrats de types à la compilation sous forme de Traits, sans nécessiter de bibliothèques ni de mécanismes particuliers. Elle s'inspire de la programmation fonctionnelle en général et d'OCaml en particulier.
Un Trait se définit comme une struct à la compilation contenant des fonctions liées à un type donné. L'article l'illustre avec un trait Reducer pour le pliage, où un type forme un réducteur sous une valeur vide et une opération de combinaison. Des traits distincts sum et product pour i32 montrent comment la même logique de réduction générique peut être réutilisée, le compilateur pouvant intégrer et dérouler la boucle. L'auteur conclut que les traits ne sont tout simplement qu'un sac de plaisir.
Source: Hacker News · Résumé par HeadlinesBriefing