Cette dĂ©pĂȘche, sous son titre Ă©nigmatique, va vous prĂ©senter un langage de programmation relativement nouveau, nommĂ© Zig, avec ses caractĂ©ristiques principales ainsi que son Ă©cosystĂšme (toolchain). Le but nâest pas de vous faire Ă tout prix adopter ce langage, mais seulement de dĂ©couvrir quelques morceaux choisis, pour le plaisir des yeux.
Sommaire
- Présentation
- Installation
- Hello, world!
- Un mot sur lâĂ©cosystĂšme
- Spécificité du langage
- Les outils
- Usage
- La version 0.11.0
- Le mot de la fin
Note : ce langage est relativement jeune, la premiĂšre version date de 2016 et la derniĂšre version stable (0.10.1) parue en janvier 2023 est dĂ©jĂ considĂ©rĂ©e comme obsolĂšte par rapport Ă la branche master ! Le dĂ©veloppement est donc trĂšs actif et les diverses documentations ne peuvent rester Ă jour bien longtemps. Une nouvelle version 0.11.0 est dâailleurs sortie pendant la rĂ©daction de la dĂ©pĂȘche.
Présentation
Le langage Zig est une idĂ©e dâAndrew Kelley. Il est lâun des contributeurs principaux et travaille Ă plein temps sur le projet.
Zig est un langage compilé impératif polyvalent, typé statiquement, « bas niveau » type C/C++/Rust. Il se décrit ainsi :
Zig est un langage de programmation gĂ©nĂ©raliste ainsi quâune toolchain ayant pour objectifs la robustesse, lâoptimisation et la rĂ©utilisation du code.
Ce langage se veut plus simple que ses prédécesseurs (« Concentrez-vous sur le debug de votre application et non sur le debug de votre connaissance du langage. ») et néanmoins puissant et sécurisé.
Il a aussi lâambition avouĂ©e dĂšs ses dĂ©buts de vouloir ĂȘtre un C meilleur que C, une vĂ©ritable Ă©volution, tout en restant compatible. Câest pourquoi vous pouvez faire en Zig tout ce que vous faisiez en C, mais en mieux.
Installation
Lâinstallation de Zig est des plus simples et universelle, puisquâil sâagit dâune simple archive tar Ă extraire. On y trouve un exĂ©cutable nommĂ© zig
qui contient tous les outils nĂ©cessaires, et quelques fichiers de documentation ainsi que la librairie standard zig. (Ă noter que la source de la libc musl est Ă©galement fournie pour pouvoir compiler un bon nombre de cibles, bien que Zig nâen dĂ©pende pas.) Le tout tient dans une petite archive de 45 Mo, ce qui est fort raisonnable.
La deuxiĂšme Ă©tape, optionnelle, consiste Ă permettre lâappel Ă lâexĂ©cutable zig
depuis nâimporte oĂč, soit en ajoutant le dossier contenant zig
au PATH
, soit en créant un lien symbolique pointant sur cet exécutable dans votre dossier bin
.
Notons que certains gestionnaires de paquets proposent dĂ©jĂ un package zig, mĂȘme si parfois celui-ci est obsolĂšte Ă cause du dĂ©veloppement trĂšs actif de Zig.
Hello, world!
Voici le traditionnel « Bonjour, le monde ! » :
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, {s}!\n", .{"world"});
}
Dans votre terminal :
$ zig build-exe hello.zig
$ ./hello
Hello, world!
Un autre exemple qui sera peut-ĂȘtre plus intĂ©ressant, il sâagit dâextraire des entiers dâune chaine de caractĂšre, sĂ©parĂ©s par des espaces ou des virgules. Ă noter que ce programme sâauto-teste :
const std = @import("std");
const parseInt = std.fmt.parseInt;
test "parse integers" {
const input = "123 67 89,99";
const ally = std.testing.allocator;
var list = std.ArrayList(u32).init(ally);
// Ensure the list is freed at scope exit.
// Try commenting out this line!
defer list.deinit();
var it = std.mem.tokenize(u8, input, " ,");
while (it.next()) |num| {
const n = try parseInt(u32, num, 10);
try list.append(n);
}
const expected = [_]u32{ 123, 67, 89, 99 };
for (expected, list.items) |exp, actual| {
try std.testing.expectEqual(exp, actual);
}
}
Dâautres exemples sont disponibles sur https://ziglearn.org/.
Vous pouvez aussi voir le code dâun TapTempo abondamment commentĂ©.
Un mot sur lâĂ©cosystĂšme
Zig fournit une chaĂźne de compilation qui compile le langage Zig, mais aussi C et C++. Cette chaĂźne de compilation prend en charge la cross-compilation ainsi que la compilation statique. Zig intĂšgre Ă©galement son propre systĂšme de construction rendant superflus lâusage de Make/Cmake/etc. Un gestionnaire de paquets est prĂ©vu, pour gĂ©rer aussi bien les bibliothĂšques Ă©crites en C quâen Zig. La version 0.11.0 a commencĂ© Ă introduire ce gestionnaire de paquets et il est dĂ©jĂ considĂ©rĂ© suffisamment stable pour ĂȘtre utilisĂ©.
Le compilateur est Ă lui seul une petite merveille puisquâil est fourni avec musl (une implĂ©mentation de la bibliothĂšque standard C) quâil compile Ă la demande et utilise pour gĂ©nĂ©rer des binaires statiques. Il peut construire des exĂ©cutables pour un grand nombre dâOS et dâarchitectures, intĂšgre un cache de compilation et quatre modes de compilation. Il supporte mĂȘme une gĂ©nĂ©ration du code en WebAssembly sans manipulations Ă©sotĂ©riques, simplement en spĂ©cifiant la cible appropriĂ©e.
Il est Ă noter quâen mode de compilation Release, le compilateur est dĂ©terministe jusque dans ses optimisations, et il produira le mĂȘme binaire pour la mĂȘme source, au bit prĂšs !
Tout ceci fait que le compilateur C du projet Zig est tout à fait honorable (voir plus pour certains) face aux principaux compilateurs C du marché.
Spécificité du langage
Quant au langage lui-mĂȘme, il est conçu pour ĂȘtre simple et lisible, sans rien de cachĂ© : ni flots de contrĂŽle, ni allocations de mĂ©moire.
Si un code en Zig ne semble pas faire appel Ă une fonction, câest quâil ne le fait pas. Lâobjectif de cette conception est dâamĂ©liorer la lisibilitĂ©.
Zig ne gĂšre pas lui-mĂȘme les allocations mĂ©moire sur le tas. Il nây a pas de mot clĂ© new
ou autre fonctionnalitĂ© qui utiliserait un allocateur de mĂ©moire (comme un opĂ©rateur de concatĂ©nation de chaĂźnes de caractĂšres par exemple). Le concept de tas est gĂ©rĂ© par une bibliothĂšque ou le code de lâapplication, pas par le langage. Le principal problĂšme avec les allocations de mĂ©moire cachĂ©es est quâelles empĂȘchent la rĂ©utilisation du code dans certains environnements. Certains cas nĂ©cessitent de nâavoir aucune allocation mĂ©moire, donc le langage de programmation doit fournir cette garantie.
La bibliothĂšque standard de Zig est entiĂšrement optionnelle. Chaque API nâest compilĂ©e dans le programme que si elle est utilisĂ©e. Zig a la mĂȘme prise en charge avec ou sans libc. Zig encourage son utilisation directement sur le matĂ©riel et le dĂ©veloppement Ă haute performance. Ceci est le meilleur des deux mondes. Par exemple, les programmes WebAssembly peuvent utiliser les fonctionnalitĂ©s habituelles de la bibliothĂšque standard, et quand mĂȘme avoir des exĂ©cutables de petite taille comparĂ©s aux autres langages prenant en charge WebAssembly.
Zig nâa pas de macros ni de mĂ©taprogrammation, et pourtant le langage exprime des programmes complexes dâune maniĂšre claire, non rĂ©pĂ©titive. MĂȘme Rust implĂ©mente en dur certaines macros, comme format!
. LâĂ©quivalent en Zig est implĂ©mentĂ© dans la bibliothĂšque standard sans code en dur dans le compilateur.
Zig 0.5.0 a introduit les fonctions async
. Cette fonctionnalitĂ© nâa pas de dĂ©pendance au systĂšme dâexploitation hĂŽte ou mĂȘme Ă lâallocation de mĂ©moire dans le tas. Cela veut dire que les fonctions async
sont disponibles pour la cible « freestanding » (sans systĂšme dâexploitation).
Dans dâautres langages de programmation, les rĂ©fĂ©rences null
sont sources dâerreurs Ă lâexĂ©cution, et sont mĂȘme soupçonnĂ©es ĂȘtre la pire erreur en informatique. Les pointeurs en Zig ne peuvent pas ĂȘtre null
. Il existe néanmoins un type optionnel.
Zig dĂ©fini un type spĂ©cial de gestion des erreurs. Les erreurs ne peuvent ĂȘtre ignorĂ©es. Zig vous permet dâĂ©numĂ©rer toutes les raisons possibles de dĂ©faillance de maniĂšre exhaustive et de traiter chacune dâentre elles de maniĂšre spĂ©cifique si vous le souhaitez. Cette Ă©numĂ©ration est produite et vĂ©rifiĂ©e par le compilateur (ce qui fait partie des particularitĂ©s du langage Zig), de sorte que vous ne pouvez manquer aucun cas. Il convient donc dâen tenir compte et de les traiter au moyen des mots-clĂ©s catch
, try
, switch
et unreachable
.
Il a Ă©tĂ© dit plus haut que Zig nâa pas de macros. Mais il a mieux. Il peut exĂ©cuter du code Ă la compilation plutĂŽt quâĂ lâexĂ©cution. En effet, une variable marquĂ©e du mot-clĂ© comptime
sera connue à la compilation. Les boucles marquées du mot-clé inline
seront exĂ©cutĂ©es Ă la compilation. Cela permet dâexĂ©cuter Ă lâavance les parties du code qui ne dĂ©pendent pas des entrĂ©es utilisateur, et dâoptimiser lâexĂ©cution, ou simplement automatiser des tĂąches rĂ©pĂ©titives pour le programmeur sans que cela ne se ressente Ă lâexĂ©cution.
Un exemple : je veux que mon programme affiche son nom Ă diffĂ©rent stade de son exĂ©cution, avec de grandes lettres en art ASCII. On dispose pour cela dâune chaĂźne de caractĂšre contenant le nom du programme, et dâune fonction foo
qui retourne une chaine avec de grandes lettres en art ASCII en Ă©change dâune chaĂźne de caractĂšre. La plupart du temps, on se contenterait dâappeler une fois la fonction foo
au dĂ©but du programme et Ă stocker dans une variable le rĂ©sultat pour lâafficher.
Mais Zig permet dâaller plus loin. Avec lâexĂ©cution Ă la compilation, on peut nâexĂ©cuter la fonction donnant les grandes lettres quâĂ la compilation, augmentant ainsi lĂ©gĂšrement le temps dâexĂ©cution. La fonction foo
nâĂ©tant pas utile Ă lâexĂ©cution, elle ne sera pas incluse dans le binaire, tout comme la chaĂźne contenant le nom du programme.
Cet exemple est trivial, mais peut vous donner un aperçu de la puissance du comptime.
Pour un article plus détaillé sur le comptime Zig, voir https://zig.news/edyu/wtf-is-zig-comptime-and-inline-257b
Vous pourrez en apprendre encore plus en lisant la vue dâensemble du projet, ou en jouant avec les ziglings !
Les outils
Il nâexiste Ă ce jour aucun IDE conçu pour Zig, mais certains Ă©diteurs de texte supportent dĂ©jĂ des fonctionnalitĂ©s telles que la coloration syntaxique. Ces Ă©diteurs sont Emacs, Vim, Kate, VS Code et Sublime Text.
Un serveur de langue est fourni Ă©galement pour les clients le supportant.
Quant au débogage, il peut se faire tout simplement avec gdb
, ou nâimporte quel dĂ©bogueur C/C++. NĂ©anmoins, le compilateur fournit des indications si prĂ©cises sur les erreurs quâon a pu commettre que le recours Ă un dĂ©bogueur pour la plupart des erreurs triviales est inutile.
Les librairies Zig, elles, sont, pour lâinstant, peu nombreuses, et il nâexiste pas dâindex « officiel » pour les rĂ©fĂ©rencer puisque la communautĂ© est dĂ©centralisĂ©e. Ă la place, on retrouve plusieurs petits index maintenus par la communautĂ©.
Il existe tout de mĂȘme un projet en cours de gestionnaire de paquet livrĂ© avec Zig, qui nâest reliĂ© Ă aucun index en particulier, et qui gĂšrera aussi bien les modules Zig que C/C++.
Usage
Zig est un langage de programmation assez généraliste, il peut donc convenir à la plupart des usages.
Il est notamment plĂ©biscitĂ© pour des programmes ayant des contraintes de performance et de consommation mĂ©moire que lâon peut retrouver dans les systĂšmes embarquĂ©s et applications en « temps rĂ©el ». Une communautĂ© dâutilisateurs (des ziguanas) dans ce domaine (zig embedded group) sâorganise autour du projet microzig afin dâoffrir lâoutillage nĂ©cessaire pour ce type de dĂ©veloppement.
On peut trouver plusieurs listes de projets Ă©crits en Zig, parmi lesquels on trouve un lecteur de flux Fediverse pour bureau GTK, un solveur de sudoku, un interprĂ©teur Brainfuck, un Ă©diteur de pixel art, un systĂšme dâexploitation, un environnement dâexĂ©cution JavaScript, un jeu RPG 2D⊠Les usages de Zig sont multiples et variĂ©s !
Zig est aussi utilisé par des entreprises comme Uber ou TigerBeetle.
La version 0.11.0
Cette sortie de version inclut 8 mois de travail : des changements de la part de 269 contributeurs diffĂ©rents, rĂ©partis dans 4457 changements. Un total de 1012 tickets rĂ©solus ! Câest Ă©galement « the dĂ©but of Package Management ».
Le mot de la fin
Zig est sous licence MIT. Lâorganisation Zig Software Foundation est une organisation Ă but non lucratif 501(c)(3)) dont lâobjectif est de soutenir le projet Zig que ce soit par la rĂ©munĂ©ration, voire, lâembauche, de dĂ©veloppeurs (Jakub Konka, Rich Felker, Meghan Denny, Andrew Kelley) ou le sponsoring dâautres projets gravitant autour du projet (Zig books par exemple ou indirectement musl).
Aller plus loin
- DĂ©pĂŽt Git de Zig (39 clics)
- Page Wikipédia de Zig (46 clics)
- Page dâaccueil de Zig (83 clics)
- Documentation de Zig (24 clics)
- Ziglings, des programmes Zig à réparer (32 clics)
- Notes de sortie de la version 0.11.0 (21 clics)
# Zig c'est la vie !
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 6.
Merci pour cette dĂ©pĂȘche !
Plus je lis sur Zig et plus j'aime ce langage.
Je ne l'utiliserai certainement pas pour tous les usages, mais quand on fait de l'embarqué ou du systÚme, c'est vraiment chouette.
Le systĂšme de build intĂ©grĂ© au langage est au dĂ©but assez dĂ©routant, mais l'idĂ©e de pouvoir tout faire dans le mĂȘme langage et avec un seul binaire est vraiment sĂ©duisante.
J'apprécie aussi particuliÚrement la possibilité de pouvoir utiliser une bibliothÚque C par un simple
@cImport
J'adore ce petit exemple, qui montre que Zig est plus lisible que C mĂȘme en appelant des bibliothĂšques C. Bref, c'est un meilleur C, comme le dit son auteur.
Le
comptime
aussi c'est juste magique, je n'ai pas encore trop joué avec, mais ça donne plein d'idées. J'avais été impressionné par le code deprint
prĂ©sentĂ© dans la doc. Ăa vaut le coup de passer un peu de temps pour comprendre une telle fonction.Ce qui est fou c'est que
comptime
permet de faire de la généricité sans rien ajouter au langage !Il y a plein d'autres aspects à explorer comme la gestion "sécurisée" des pointeurs.
Il y a aussi plein de conf intĂ©ressantes Ă voir sur le sujet, notamment celle sur le recodage de la libC, malheureusement je n'arrive pas remettre la main dessus, peut-ĂȘtre que c'Ă©tait pas ça le titreâŠ
Bref, c'est un beau projet qui a de beaux jours devant lui.
# Mais pourquoi diantre pas de RAII ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 10.
Merci beaucoup pour cette dĂ©pĂȘche trĂšs sympa ;-)
Je trouve globalement Zig trÚs rafraßchissant et bourré de bonnes idées.
Typiquement l'intĂ©gration d'un compilo C capable de cross-compilation dans quelques dizaines de Mo. Ăa donne mĂȘme des idĂ©es pour les logiciels ayant besoin d'embarquer un compilo pour faire du JIT.
Bref j'en arrive à ma question: mais pourquoi donc des gens aussi compétents refusent de mettre du RAII (c'est à dire des fonctions destructeur appelées automatiquement quand un objet se fait free ou bien est enlevé de la stack) ?
De ce que je comprends l'argument avancé c'est:
1 - c'est pour qu'il n'y ait rien de caché
2 - c'est plus lisible car c'est explicite
Pour le premier point on peut objecter que nos CPU modernes ne se privent pas pour faire toute sorte de magie noire avec notre code (out-of-order, processeur super-scalaires).
L'OS de sont cĂŽtĂ© dĂ©cide arbitrairement du scheduling des threads, dĂ©clenches des interruptions quand ça lui chante et fait semblant dâallouer de la mĂ©moire quand on fait un malloc pour finalement tuer notre process sur un out-of-memory quand il a Ă©tĂ© trop optimisteâŠ
Bref des choses cachées quand on un impact sur notre programme c'est pas ça qui manque dans un ordinateur moderne !
Le second point me semble encore plus incompréhensible: on se retrouve avec un pattern consistant à systématiquement devoir écrire
var foo = init(); defer foo.destroy();
.- Si on oublie le defer on a fait un bug
- Donc faut faire gaffe à ça en code review
- Et faut des outils pour détecter ce type d'erreurs
- Et ça peut ĂȘtre plein de classes de bug: memory leak, resource leak (e.g. on ne ferme pas un fichier), deadlock (e.g. la ressource reprĂ©sente la prise de mutex)
En rÚgle générale avoir un langage qui permet d'exprimer des structures ne pouvant pas représenter un état invalide est un gain énorme (exemple typique: en Rust un mutex contient l'objet qu'il protÚge, de fait il est impossible d'accéder à ce dernier sans avoir pris le mutex).
Et si on veut pinailler,
defer
est dĂ©jĂ quelque de magique vu qu'on n'est pas explicite sur l'endroit oĂč sera fait l'appel de fonction (j'imagine que personne n'est assez fou pour dĂ©fendre l'utilisation de free sans defer ni RAII comme en C ).De fait plutĂŽt qu'un
defer
, j'aurai plutÎt vu un mot clé permettant d'indiquer qu'une fonction retournait un object avec destructor.Quitte à devoir explicitement fournir le destructeur dans la fonction d'initialisation si on veut rester plus explicite, par exemple:
On peut mĂȘme obliger les variables raii Ă avoir un nom particulier (genre avec un symbole en prĂ©fixe) Ă©tant donnĂ© que la variable peut survivre Ă la fonction l'ayant crĂ©Ă©e (typiquement en la retournant Ă l'appelant), ce qui Ă©tait moins utile pour le defer car il s'exĂ©cute uniquement dans la fonction d'oĂč il est dĂ©clarĂ©.var foo = raii foo_factory() -> foo_destructor; // pseudo syntax,
Bref, de ma fenĂȘtre le RAII apporte des avantages monstrueux comparĂ©s Ă ses "inconvĂ©nients" thĂ©orique (et ça semble plutĂŽt simple de faire un defer sous stĂ©roĂŻde qui garde le meilleurs des deux mondes). Et du coup je n'arrive Ă comprendre le raisonnement des devs de Zig (qui, je le rappelle sont des mecs sacrĂ©ment brillants !)
Dernier point: on n'est pas vendredi, ce post n'est pas un troll (ni un flim sur le cyclimse). Il est bien possible que j'ai fait un homme de paille sans le vouloir avec les arguments pour l'absence de RAII, si c'est le cas merci de me corriger dans la joie et la bonne humeur ;-)
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par xryl669 . ĂvaluĂ©Â Ă Â 1.
En mĂȘme temps, vu que Zig peut utiliser un "module" C++ qui lui supporte le RAII, rien ne t'empĂȘche de RAIIser ton code en C++ et de l'utiliser dans Zig, non ?
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par abriotde (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 1.
Le RAII, c'est surtout de la performance processeur en moins (car il faut surveiller l'état des variables à l'exécution) et en embarqué c'est aussi une consommation mémoire non maßtrisé (on ne sait pas quand il va passer libérer la mémoire).
Le RAII simplifie grandement la programmation mais quand on recherche des performances optimale, c'est du gùchis. Enfin la solution C++ est pas mal avec les smartpointer que l'on peut utiliser quand on accepte cette "perte" pour plus de productivité.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 7.
Je pense que tu confonds RAII et garbage collector ;-)
RAII n'a strictement aucun impacte au runtime: c'est le compilo qui dĂ©termine oĂč une variable n'est plus utilisĂ©e et met Ă cet endroit le code d'appel du destructeur.
Si tu ne fais pas de RAII tu devras mettre Ă la main l'appel au destructeur au mĂȘme endroit (dans tous les cas faut bien faire un close sur le file descriptor ou un free sur le buffer !).
(et les smartpointers de C++ sont implémentés grùce au RAII)
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par abriotde (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 2.
Le compilo ne peut pas toujours savoir quand mettre un appel au destructeur. Les smartpointer, c'est en quelques sortes un garbage collector compilĂ© avec le code (Enfin, c'est Go qui fonctionne rĂ©ellement comme ça). Mais au lieu d'avoir un processus sĂ©parĂ© qui regarde le nombre de pointeurs sur chaque instance le smartpointer vĂ©rifie s'il est Ă 0 et dĂ©truit l'instance si besoin (le travail du GC). Certes, l'implĂ©mentation est sans doute un peu plus complexe/optimisĂ© avec des destruction "prĂ©visibles" mais c'est le principe. Il y a donc du code qui "compte et regarde", c'est de la ressources perdu. Certes c'est peanuts, mais des variables, il peut y en avoir beaucoup, sur des langages ou tout est gĂ©rĂ© ainsi, l'incidence est loin d'ĂȘtre nĂ©gligeable.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 8.
Mais là tu parles de garbage collector (dont une des implémentation est le compteur de références qui est mis en oeuvre dans les smartpointers C++)
Le garbage collector est utilisé uniquement pour les allocations dynamiques (si une allocation a lieu sur la stack, on sait que sa durée de vie est liée à l'appel de fonction l'ayant créé, donc pas besoin de check à la runtime pour savoir quand la libérer).
Le RAII est un concept orthogonal au garbage collector: si ton smartpointer est capable de dĂ©crĂ©menter le compteur de rĂ©fĂ©rence et de faire la libĂ©ration de mĂ©moire quand celui-ci arrive Ă zĂ©ro, c'est bien que du code a Ă©tĂ© appelĂ© automatiquement quand la variable contenant le smarpointer a Ă©tĂ© dĂ©truite. Et cela quelque soit l'endroit oĂč se trouve la variable ne question (stack, dans une structure elle-mĂȘme sur le tas etc.).
De plus le RAII peut servir a gérer autre chose que de la mémoire: fichier/socket ouvert, mutex etc.
(et Go n'utilise pas de compteur de référence pour son garbage collector, mais du mark and sweep)
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 2.
Zig a déjà des mécanismes permettant de détecter les fuites de mémoire (sauf en ReleaseFast), mais c'est vrai que le principe de RAII est intéressant.
ça s'implémente bien en C++ car il y a cette notion de destructeur. Dans un langage comme Zig, il faudrait trouver un moyen d'associer une fonction à une structure de donnée qu'on alloue.
AprĂšs, comme tu le dis, ça pourrait passĂ© par une sorte de "super defer" ou peut-ĂȘtre justement par les allocateurs ?
Comme on passe l'allocateur, on pourrait peut-ĂȘtre prĂ©ciser si la mĂ©moire doit ĂȘtre libĂ©rĂ©e Ă la sortie du scope ? Bon dans tous les cas, tu pourrai oubliĂ© d'utiliser cet allocateur.
De ce que j'avais compris des premiĂšres prĂ©sentation de Zig, Andrew semblait avoir des idĂ©es pour amĂ©liorer la gestion de la mĂ©moire. Le langage est encore jeune, peut-ĂȘtre que ce genre de changement est encore possible ? Ăa a peut-ĂȘtre Ă©tĂ© proposĂ© (j'ai pas regardĂ©) ?
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 6.
J'en rajoute une couche avec ce post de l'auteur de Zig
Il semble considérer que le defer fait office de RAII. Mais c'est oublier que le defer s'exécute quand on quitte la fonction dans laquelle il a été déclaré. Du coup on ne peut pas retourner des objets avec destructeur.
Par exemple:
va retourner (vous pouvez aller sur https://zig-play.dev/ pour jouer avec):
taking lock!
Lock!
Unlock!
lock taken [...] !
alors qu'un langage supportant le RAII n'aurait libéré le lock que quand
guard
n'est effectivement plus référencé, c'est à dire à la fin de la fonctionmain
 !Et puisque maintenant c'est Vendredi, je vous laisse avec la justification pour fermer l'issue pour faire du vrai RAII en Zig ;-)
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 2.
Hum, oui mais en Zig tu ne l'aurai pas codé comme ça. Vu que Zig n'a pas de notion de destructeur, t'es obligé de mettre ton defer (et le unlock) dans le main (c'est d'ailleurs ce qu'il fait dans le post reddit que tu as cité).
La proposition du mot clé
clean
est intéressante, aprÚs je ne sais pas si ça rentre dans la philosophie du langage car ça masque le fait que ça va appeler une fonction, puis tu pourrai toujours oublié d'appelerclean
.Mais c'est moins verbeux que ce qui est pratiqué aujourd'hui.
Je comprends la volontĂ© du/des crĂ©ateurs de Zig d'ĂȘtre trĂšs conservateurs sur ce qui rentre ou pas dans le langage. AprĂšs, je trouve que cette gestion de la mĂ©moire avec allocateur explicite est trop lourde dans bien des cas, c'est pourquoi je rĂ©serverai Zig pour de l'embarquĂ©, de la programmation systĂšme ou des librairies qui ont besoin d'ĂȘtre trĂšs optimisĂ©es (genre librairie standard d'un langage, ce que fait Bun ou Roc).
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 4. DerniĂšre modification le 13 septembre 2023 Ă 00:08.
Oui tout Ă fait, mais du coup on se retrouve avec une fonction qui retourne une ressource devant ĂȘtre impĂ©rativement nettoyĂ©e⊠mais rien pour garantir que ce sera fait ! (le fameux RTFM quoi ÂŻ\(ă)/ÂŻ )
C'est le retour du bug classique façon:
La solution qu'a choisi Zig pour contrer ce problÚme est un puissant systÚme de vérification à la runtime quand on compile avec le profile de test (et aussi en mode release-safe).
C'est largement mieux que C, mais ça ne vaut pas une vérification exhaustive à la compilation (comme permet le RAII): on ne détectera le problÚme que si on passe dedans pendant notre phase de test.
Et donc c'est typiquement le code peu utilisé (ou galÚre à tester) genre gestion de cas d'erreur dans un cas aux limites qui se retrouve à contenir des bugs (comprendre: les bugs les plus horribles à reproduire)
Enfin, autant ce type de checks marche pour vĂ©rifier des erreurs d'allocations genre use-after-free, autant il n'est d'aucune utilitĂ© pour de la gestion de ressource comme dans mon exempleâŠ
J'ai l'impression que Zig est trÚs séduisant pour les devs C car on garde la philosophie une trÚs forte compatibilité avec le C (Zig se vent comme étant capable de s'intégrer dans un projet C existant) tout en fournissant un langage avec tooling et écosystÚme au bas mot 20ans en avance par rapport au C99⊠Ho wait !
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par reno . ĂvaluĂ©Â Ă Â 3.
Vale un language en alpha a mĂȘme un RAII ou les destructeurs peuvent prendre des paramĂštres:
https://verdagon.dev/blog/higher-raii-7drl
[^] # Re: Mais pourquoi diantre pas de RAII ?
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 1.
Merci pour la découverte, je ne connaissais pas ce langage !
# Que du bon
PostĂ©Â par steph1978 . ĂvaluĂ©Â Ă Â 6.
Je ne me suis pas lancé dans Zig car cela reste pour moi un langage compliqué, comme Rust, et dont je n'ai pas usage immédiat. Je ne fais pas de programmation systÚme. Je suis plus sur du Python/Nim/Elixir.
Mas j'adore les contenus à propos de zig, vidéos et billets de blog. Je trouve que c'est plein de bonnes idées, que le créateur a semble visionnaire et trÚs sympathique, la communauté trÚs animée.
Il commence à y avoir plein de bonnes réalisations. En vrac: une réécriture de ncdu, écrire des traitements rapides pour Elixir (en fait pour la BEAM), un serveur web.
Ă noter, Uber utilise Zig comme beaucoup de monde : pour sa toolchain qui permet de (cross-)compiler du C.
Je l'ai utilisé pour cross-compiler du Nim de amd64 vers arm7, c'est terriblement efficace, par rapport à gcc.
Mais le projet se questionne sur ce qui semble une bonne idĂ©e pour crĂ©er de l'adoption mais pourrait les freiner dans le dĂ©veloppement d'une toolchain plus efficace pour le langage lui-mĂȘme.
Un langage réussi c'est un mélange de:
- ses fonctionnalités, sa syntaxe : comment ça m'aide à produire du code qui me plait
- son tooling : comment je passe du code Ă qqch qui tourne
- son Ă©cosystĂšme, bibliothĂšque, framework : comment je ne pars pas de rien
- sa communauté : comment j'obtiens de l'aide, des idées
Je pense que Zig est bien parti sur tous ces aspects.
[^] # Re: Que du bon
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 2.
Je ne savais pas qu'ils souhaitaient Ă long terme se dĂ©faire de LLVM. C'est un noble objectif et en mĂȘme temps super ambitieux !
Ils ont l'air d'ĂȘtre dĂ©terminĂ© et j'ai hĂąte de voir ce que ça peut donner.
# Les pointeurs peuvent ĂȘtre null
PostĂ©Â par xryl669 . ĂvaluĂ©Â Ă Â 1.
Contrairement Ă ce qui est indiquĂ© dans l'article, on peut parfaitement avoir des pointeurs null dans Zig. Cf cet exemple. Sinon, impossible d'implĂ©menter une liste chaĂźnĂ©e, une queue, etcâŠ
[^] # Re: Les pointeurs peuvent ĂȘtre null
PostĂ©Â par alberic89 đ§ . ĂvaluĂ©Â Ă Â 4.
C'est une diffĂ©rence subtile, les pointeurs peuvent ĂȘtre optionnels et donc avoir la valeur
null
. Et ça change tout.C'est expliqué ici : https://ziglang.org/documentation/master/#Optionals
L'informatique n'est pas une science exacte, on n'est jamais Ă l'abri d'un succĂšs
# bien mais pas top
PostĂ©Â par abriotde (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 0. DerniĂšre modification le 08 septembre 2023 Ă 10:19.
Pour moi Rust est juste mieux quand on veut de la performance, il permet de tout optimiser:
- allocation mémoire sûr (plus que Zig)
- macro qui permettent de dĂ©porter Ă la compilation tout ce qui peut l'ĂȘtre (mĂȘme plus que C)
Alors certes Rust est plus complexe (quoique) mais si on veut des performances au top⊠sinon on prends Go ou Java.
Zig n'est pas inintéressant pour autant.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: bien mais pas top
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 6.
Je ne comprend en quoi Rust est plus performant concernant l'allocation mémoire ?
Ni en quoi les macros de Rust sont plus efficaces que le
comptime
de Zig.Pour moi, l'intĂ©rĂȘt principal de Rust reste la garantie qu'il n'y aura pas de problĂšme avec la mĂ©moire (fuite etc.), mais niveau perf, ce sont deux langages qui permettent d'avoir des performances similaires.
Peut-ĂȘtre mĂȘme que Zig encourage des façon de coder plus adaptĂ©s Ă la performance, comme le "Data Oriented Design", notamment avec des sucres syntaxiques pour pouvoir facilement boucler sur des structures de tableaux.
En tout cas, Zig est rĂ©putĂ© pour permettre d'Ă©crire du code extrĂȘmement performant.
[^] # Re: bien mais pas top
PostĂ©Â par steph1978 . ĂvaluĂ©Â Ă Â 2.
Et encore, en Rust, ponctuellement, pour de la perf, tu as besoin de muté in place et donc de passer en
unsafe
. C'est trĂšs propre car tu sais exactement oĂč c'est fait dans le code (CTRL+F "unsafe") mais il n'y a pas de magie.[^] # Re: bien mais pas top
PostĂ©Â par abriotde (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 2.
C'est peut-ĂȘtre que je ne connais pas assez Zig, mais je trouve que Rust apporte plus (Notamment les sucres syntaxiques me semble pas vraiment plus lisible). Rust apporte aussi une programmation fonctionnelle puissante, et la sĂ©curitĂ© n'est pas rien.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: bien mais pas top
PostĂ©Â par uso (site web personnel) . ĂvaluĂ©Â Ă Â 2.
Bah ça me semble logique que Rust apporte plus, vu qu'il me semble que zig a pour but de rester un langage assez simple.
Donc moins de maniĂšre d'exprimer la mĂȘme chose.
Rust, c'est cool, mais les code avec 8 itérateurs chainé, ce n'est pas ce qu'il y a de plus simple ni de plus reposant à lire.
# Optimisation explicite ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 2.
« En effet, une variable marquĂ©e du mot-clĂ© comptime sera connue Ă la compilation. Les boucles marquĂ©es du mot-clĂ© inline seront exĂ©cutĂ©es Ă la compilation. » Je ne vois pas cela comme un avantage. Ce genre d'optimisation, devrait ĂȘtre implicite, le compilateur reconnaissant ce qui peut se faire Ă la compilation, sans avoir besoin d'un mot-clĂ© particulier.
[^] # Re: Optimisation explicite ?
PostĂ©Â par G.bleu (site web personnel) . ĂvaluĂ©Â Ă Â 3.
Cette histoire de
inline for
m'a aussi encouragé à creuser, et il semblerait que le compilo fait parfois des choses inattendues.Par exemple en Rust, il ne faut pas utiliser la variable d'incrément dans une boucle for.
En plus il faut prendre en compte le fait que chaque version du compilo peut changer l'heuristique, donc un code qui faisait du loop unrolling peut ne plus le faire.
J'imagine que c'est encore pire pour le C oĂč il y a plein de compilos diffĂ©rents avec chacun leur heuristique pour faire le loop unfoldingâŠ
Bref ça semble légitime d'avoir un
inline for
pour s'assurer que le comportement est bien celui attendu, typiquement si on est sur une plateforme embarquée ou la place/puissance est comptée.[^] # Re: Optimisation explicite ?
PostĂ©Â par abriotde (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 3.
Et surtout parfois, des variables peuvent ĂȘtre modifier, des boucles "innutiles" en apparences utiles⊠Les bons compilateurs essayent dĂ©jĂ de prĂ©-compiler un maximum de chose (1000*1000 sera traduit en 1000000) mais ils sont vite limitĂ©s par ce qui pourrait avoir un sens diffĂ©rent. Classiquement, l'Ă©valuation de certaines fonctions basiques peut changer.
Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.
[^] # Re: Optimisation explicite ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 3.
En fait, aprÚs avoir appris Zig (notamment via l'excellent Ziglings), et relu plus soigneusement l'article, je me rends compte que le but d'inline n'est pas du tout l'optimisation (qu'il vaut mieux laisser au compilateur) mais c'est plutÎt, comme comptime, un mécanisme pour remplacer les macros.
# Et le parallélisme ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 4.
Sauf erreur, cette dĂ©pĂȘche ne parle pas du tout de la programmation parallĂšle (une grosse faiblesse de Rust et la principale raison pour laquelle Rust ne m'intĂ©resse pas trop, par rapport Ă Go ou Elixir). Que permet Zig dans ce domaine ?
[^] # Re: Et le parallélisme ?
PostĂ©Â par alberic89 đ§ . ĂvaluĂ©Â Ă Â 3.
Je ne suis pas sûr de bien comprendre la question, mais Zig permet l'utilisation de fonctions
async
et fournis un certain nombre de mot-clés. Malheureusement, il y a eu une régression pour la 0.11.0 et les fonctionsasync
ne sont pas disponibles pour cette version de Zig.L'informatique n'est pas une science exacte, on n'est jamais Ă l'abri d'un succĂšs
[^] # Re: Et le parallélisme ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 3.
Ăa me parait un mĂ©canisme de trĂšs bas niveau. Pas de moyen d'avoir plusieurs fils d'exĂ©cution ? Comment on utiliserait ce mĂ©canisme pour, par exemple, un serveur rĂ©seau ? J'ai regardĂ© le code du serveur HTTP Zap et je ne vois absolument pas comment il fait (en tout cas, il n'utilise pas async/await).
[^] # Re: Et le parallélisme ?
PostĂ©Â par alberic89 đ§ . ĂvaluĂ©Â Ă Â 1.
à ma connaissance, Zig n'inclut que ce systÚme dans sa syntaxe, qui est mieux expliquée ici, et en quoi elle permet de faire du parallélisme : https://kristoff.it/blog/zig-colorblind-async-await/
Mais je suppose qu'il existe des tas de librairies C et bientÎt des librairies Zig qui implémentent des fonctions beaucoup plus avancées.
L'informatique n'est pas une science exacte, on n'est jamais Ă l'abri d'un succĂšs
[^] # Re: Et le parallélisme ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 2.
On va dire que c'est une question de goût. Comme l'auteur de l'article cité (dans son dernier paragraphe), je préfÚre du vrai parallélisme au modÚle à évÚnements, qui est de plus bas niveau et décevant dans un langage conçu récemment.
[^] # Re: Et le parallélisme ?
PostĂ©Â par dzamlo . ĂvaluĂ©Â Ă Â 7. DerniĂšre modification le 09 septembre 2023 Ă 13:43.
En quoi le parallélisme est-il une faiblesse de rust?
Il me semble que c'est au contraire plutĂŽt une force, avec le systĂšme de type/ownership qui Ă©vite certaines erreurs comme les data-races, la bibliothĂšque rayon ou encore async/tokio pour le io-bound.
[^] # Re: Et le parallélisme ?
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 4.
La faiblesse est justement que Rust ne propose rien pour le parallélisme, uniquement des évÚnements (async/await).
[^] # Re: Et le parallélisme ?
PostĂ©Â par Bruno Michel (site web personnel) . ĂvaluĂ©Â Ă Â 6.
Ăa dĂ©pend pas mal de ce que l'on appelle parallĂ©lisme. Rayon citĂ© juste au-dessus permet de faire du parallĂ©lisme sur des donnĂ©es, ie utiliser facilement plusieurs coeurs CPU pour faire du calcul.
Par contre, si on parle de parallĂ©lisme dans un contexte avec beaucoup d'IO, il y a async/await et tokio. Et lĂ , les avis sont beaucoup plus partagĂ©s, on va dire. Certains apprĂ©cient que Rust reste bas-niveau, tout en Ă©vitant les bugs oĂč des donnĂ©es partagĂ©es peuvent ĂȘtre lues/Ă©crites depuis plusieurs contextes d'exĂ©cution. D'autres regrettent que ça reste bas niveau et peu pratique Ă utiliser. Il y a https://bitbashing.io/async-rust.html qui a pas mal fait parler de lui ces derniers temps.
[^] # Re: Et le parallélisme ?
PostĂ©Â par GuieA_7 (site web personnel) . ĂvaluĂ©Â Ă Â 9.
Rust, Go & Elixir sont des langages trÚs différents, et leur approches du parallélisme est du coup différente :
Dans la mesure oĂč tu regardes du cĂŽtĂ© de Go & Elixir, mĂȘme si tu ne le prĂ©cises pas, je suppose que tu envisages ces langages dans le cadre d'un service rĂ©seau. Le parallĂ©lisme de Rust est trĂšs bien si tu veux faire un moteur 3D par exemple, mais c'est sĂ»r qu'il n'aura pas forcĂ©ment la facilitĂ© d'utilisation des goroutines/micro-processus Erlang dans des cas plus spĂ©cifiques.
Si j'ai bien compris il existe en Rust plusieurs bibliothĂšques permettant d'utiliser async/wait (comme vu au dessus, vu les objectifs "systĂšme" du langage, imposer un runtime de base n'est pas souhaitable), mais on n'arrive pas Ă la facilitĂ© d'utilisation des routines (on a les garanties de Rust en compensation). J'ai aussi vu passer des systĂšmes d'acteurs façon Erlang pour Rust ; ça me semble une piste trĂšs intĂ©ressante, mais tout va dĂ©pendre de la maturitĂ©/pĂ©rennitĂ© de ces briques Ă©videmmentâŠ
Pour rĂ©pondre Ă ta question, bien que ne connaissant pas vraiment Zig, vu ses objectifs (systĂšme etcâŠ), je suppose que sa situation doit ĂȘtre Ă comparer Ă celle de Rust.
[^] # Re: Et le parallélisme ?
PostĂ©Â par AndrĂ©as Livet . ĂvaluĂ©Â Ă Â 2.
Merci pour ce commentaire pertinent.
Je connais mal Rust (j'en ai fait un tout petit peu), mais je croyais qu'il contenait des mécanismes plus poussés pour le parallélisme.
Dans mon souvenir, un des auteurs de Rust disait l'avoir créer justement car c'était difficile d'écrire du code parallÚle fiable en C++.
Si je comprends bien, avec Rust on a une garantie de fiabilité, mais pas plus d'outil que ça pour écrire facilement du code parallÚle.
J'ai beaucoup entendu parlé de lib comme tokio et les retours que j'ai pu avoir c'est que c'est trÚs puissant, mais difficile à appréhender.
[^] # Re: Et le parallélisme ?
PostĂ©Â par xryl669 . ĂvaluĂ©Â Ă Â 7.
Franchement, on en fait tout une histoire de faire du code parallÚle, mais il est sacrément plus difficile de faire du code perpendiculaire.
Là , aucun langage ne propose quoi que ce soit, surtout dÚs qu'il s'agit d'utiliser un nombre de dimensions supérieures à 2.
Ă la limite, il y aurait le brainfuck:
[^] # Re: Et le parallélisme ?
PostĂ©Â par barmic 𩩠. ĂvaluĂ©Â Ă Â 5.
C'est surtout que ça rĂ©pond Ă des besoins trĂšs diffĂ©rents mĂȘme si le vocabulaire employĂ© se chevauche beaucoup entre les 2 usagesâŻ:
Ăvidement il est rare d'ĂȘtre tout l'un ou tout l'autre et il faut savoir comment les combiner pour tirer le meilleur parti pour ton besoin.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
# Nim
PostĂ©Â par Mildred (site web personnel) . ĂvaluĂ©Â Ă Â 3.
Zig est vraiment pas mal, surtout dans son aspect de compilation ou il permet de cross-compiler du C ce qui n'est en général pas facile.. J'ai découvert Zig pour la premiÚre fois lorsque je l'ai vu mentionner dans la communauté Nim, un autre langage dont j'ai compris que Zig était issu.
Nim est un langage compilé qui utilise une syntaxe qui s'approche du Python, mais ce n'est pas là le mieux. Comme Zig, il a été précurseur pour l'exécution de code à la compilation et Nim est à la fois un interpréteur et un compilateur. A la différence de Zig, il possÚde par contre un systÚme de macros trÚs étendu qui permet de faire pratiquement n'importe quoi avec le langage. C'est comme du Lisp mais avec une syntaxe accessible. Et en fait, les macros sont des bouts de codes exécutés à la compilation et qui utilisent l'arbre syntaxique et peuvent le transformer presque dans n'importe quel sens.
Nim se place un peu plus haut niveau et gĂšre les allocations et destructions mĂ©moire. Nim v1 possĂ©dait un garbage collector classique mais avec Nim v2 on passe sur un comptage de rĂ©fĂ©rence moderne (ARC) avec des optimisations pour gĂ©rer le dĂ©placement mĂ©moire et d'autres cas. Il possĂšde Ă©galement une dĂ©tection de cycles (ORC). Le gros avantage de la gestion ARC/ORC c'est que les allocations / destructions sont dĂ©terministes. TrĂšs utile pour de l'embarquĂ© ou mĂȘme lorsqu'on se soucie des performances mĂ©moire d'un programme. Et de plus cela permet de basculer progressivement vers quelque chose qui ressemble au RAII mĂȘme si la lib standard n'est pas adaptĂ©e à ça encore.
# Mon expérience de débutant Zig
PostĂ©Â par StĂ©phane Bortzmeyer (site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 5.
Cet excellent résumé m'a motivé pour essayer Zig, j'en rends compte dans cet article : https://www.bortzmeyer.org/mes-debuts-en-zig.html
Suivre le flux des commentaires
Note : les commentaires appartiennent Ă celles et ceux qui les ont postĂ©s. Nous nâen sommes pas responsables.