Rust, une alternative fiable?

Le problème exposé dans ce sujet a été résolu.

Je pense sincèrement que n’importe quel langage demande un bagage préalable si tu n’as pas un cours qui te prend par la main pour l’apprendre (ce que le book de Rust n’est pas, on est bien d’accord). C’est bien pour ça que le SdZ avait été créé à l’époque. Et quel que soit le langage, il n’y a pas grand chose à attendre des créateurs du langage : par exemple, ce n’est pas Peyton-Jones qui a écrit Learn You a Haskell

Maintenant, il est évident qu’avoir un bagage en programmation fonctionnelle aide pour apprendre Rust. Mais je ne pense pas que la programmation fonctionnelle en soi rende l’apprentissage du langage plus facile qu’un bagage en POO. Je m’explique.

Rust est très loin d’être un langage fonctionnel. Même s’il en utilise des bouts, comme le type Option ou le filtrage par motifs, sur de nombreux aspects, les réflexes de la programmation fonctionnelle n’y sont pas applicables, entre autres pour les raisons suivantes.

  • Il n’y a pas de HKT et au rythme où ça avance, je doute qu’il y en ait un jour.
  • Il n’existe pas d’interface unique permettant de passer des fonctions en argument ou en valeur de retour (y’en a quatre différentes, quand même…).
  • Ces deux points transforment en calvaire la création de toute monade digne de ce nom.
  • Le système de fonctions constantes est absolument moisi, même s’il y a plus d’espoir de le voir devenir quelque chose de correct que pour les HKT.
  • La programmation idiomatique utilise généralement des boucles sur des itérateurs plutôt que des map ou de la récursion.

Tout ça pour dire que quelqu’un qui ne connaîtrait que la programmation fonctionnelle s’en prendrait plein la gueule avec le système d’objets, aussi rudimentaire soit-il, l’absence de tout un tas de trucs pratiques, les itérateurs, etc. Toutes choses qui ne poseront aucune difficulté à qui vient du monde OO.

Ce qu’il se passe, c’est que sauf rares exceptions, les gens qui ont un bagage en programmation fonctionnelle ont aussi un bagage dans un paradigme plus courant.

Les autres critiques que je faisais étaient que je trouve bizarre d'être si rigide quand on fait un pop et aussi laxiste que les autres langages quand on récupère un élément directement (avec les crochets).

Je ne vois pas ce qu’il y a de si bizarre, en fait. Il n’y a pas de types dépendants en Rust : le type donne juste une indication de type et ne contient aucune information sur les données effectivement contenues. Comme ce n’est sans doute pas très clair, prenons un exemple.

Le type Vec<T> se contente de dire « ceci est une collection qui peut contenir des objets de type T ». Et les fonctions d’accès, que ce soit [] ou get prennent en entrée « une collection qui peut contenir des objets de type T ».

Si on avait des types dépendants, on pourrait définir un truc comme Vec<T, N ∈ ℕ>, soit « une collection qui prend un nombre entier positif ou nul d’objets de type T ». Et un vec![1, 2, 19] aurait pour type Vec<i64, 3>. Et surtout, la fonction pop aurait pour type Vec<T, N ∈ ℕ*> -> (Vec<T, N-1>, T). Et il deviendrait alors impossible de passer un vecteur vide à la fonction.

Sauf erreur de ma part, ce genre de choses est possible en Idris, par exemple. Mais on voit bien que si on combine ça avec de la mutabilité, ça commence à devenir vraiment sale…

Du coup, dans la mesure où le système de typage ne permet pas en soi d’interdire de passer à la fonction un objet du bon type mais contenant les mauvaises données, et qu’il n’y a aucune intention de le faire, eh ben on laisse au programmeur sa responsabilité. Tu as ainsi un accesseur rapide mais risqué [] et un accesseur plus lent mais sans risque get. ;)

Ainsi que les messages d'erreur du compilateur complètement illisibles à l'époque (liée à la jeunesse du langage) – toi tu les dis géniaux, donc j'imagine qu'ils ont fait de gros progrès.

Vu ce que tu décris dans ton message d’origine, les messages d’erreurs sont toujours les mêmes plus ou moins. Là où on n’est pas d’accord, c’est quand tu dis qu’ils sont illisibles. Le message d’erreur que tu as rencontré pointait exactement le problème rencontré, dès la première ligne, et avec une formulation qui ne laissait aucune place au doute :

Le trait Display n’est pas implémenté pour le type Option.

Je conçois qu’étant nouveau, on puisse ne pas connaître le trait Display, voire le type Option (encore que, comme le pointait Eusèbe, si tu utilises une fonction qui renvoie un type Option sans te renseigner sur ce que c’est, c’est toi le fautif…).

Mais alors, tu cherches dans la doc ce que c’est que ce Display. Dont l’explication n’est pas très claire, on est d’accord, mais qui redirige immédiatement vers cette page où tout est expliqué en détail et, a minima, tu comprendras qu’il y a un problème avec l’affichage.

Maintenant, on ne peut pas vraiment faire mieux comme message d’erreur.

  • La fonction Vec::pop() renvoie un Option, c’est prévu pour et parfaitement légal.
  • Rien ne t’oblige à déstructurer ton Option, tu peux parfaitement continuer à travailler directement dessus, il n’y a donc aucune raison que le compilateur râle à ce sujet.
  • Il est parfaitement légal de passer n’importe quelle variable à la macro println!(), ne serait-ce que parce que les macros ne vérifient pas les types (même si on l’utilise comme une fonction, il faut voir ça plus comme une macro C qui va te remplacer ça par un bloc dégueulasse chargé du formatage et de l’affichage).
  • La fonction chargée de réaliser le formatage dans le cas général n’existe pas pour Option → erreur, et message lié.
+2 -0

Je n'ai pas grand-chose à dire sur ton message. Je me doute bien que les choix concernant ce langage n'ont pas été faits n'importe comment. Je réagis juste sur ça :

comme le pointait Eusèbe, si tu utilises une fonction qui renvoie un type Option sans te renseigner sur ce que c’est, c’est toi le fautif…

Se renseigner est une chose, mais je n'avais pas compris ce que je lisais. Probablement parce que la vraie information qui m'échappait était considérée évidente : qu'est-ce que la patern matching (maintenant, je sais ce que c'est, donc je ne plus me remettre dans les conditions de l'époque) ? Un problème de bagage, donc (mais je doute être le seul dans ce cas, loin de là !). Et c'est là que la communauté joue, comme tu le signales toi-même.

Pour finir, je dirai que quand on ne sait pas ce qu'on cherche, c'est très compliqué de le trouver. Je comprends nettement mieux la doc de Rust qu'à l'époque, mais il a fallu de longues explications de Berdes et Eusebe pour savoir ce que je cherchais. Mais je n'ai pas envie d'avoir ce problème pour chaque nouvelle notion que je croiserai en Rust, donc je suis parti ailleurs, et je reviendrai peut-être dans un ou deux ans (si l'attrait pour ce langage n'est pas retombé).

+0 -0

A propos de l'apprentissage du Rust, avez-vous des liens vers des exercices qui permettent de saisir les subtilités du langages, qui obligent à utiliser toute la force du langage (ceux que j'ai trouvé sont très génériques: calculette de base, jeu du plus ou moins mais j'aimerais des exercices qui utilisent les spécificités du langage)

Je n’en connais pas. Après, le moyen le plus sûr de s’exercer, c’est encore de e fixer un objectif et de programmer jusqu’à y arriver. Tu n’as besoin d’aucune correction pour voir si le résultat fonctionne selon les objectifs fixés au départ ou non, et si tu es bloqué, ou si tu as besoin d’avis sur les solutions auxquelles tu parviens, les forums sont là pour t’aider. :)

+0 -0

En ce qui me concerne, j'ai également très vite déchanté en essayant Rust, en faveur de Go. Pas faute d'avoir lu la doc, mais plutôt (et justement) parce que j'avais besoin d'aller la lire toutes les 10 secondes pour faire le moindre truc.

Vu la courbe d'apprentissage, je reste assez réservé sur son utilisation sur le long terme. En tout cas, certainement pas pour une pratique en dilettante.

Je pars du principe qu'un bon langage est un langage qui ne pète pas les noix de son utilisateur. Ce qui est évident à concevoir n'a aucune raison de devenir compliqué à coder au premier abord. Soit le contraire de mes premières expériences avec Rust.

+3 -2

nohar: c'est très relatif comme définition, Rust ne me pète pas tant que ça les noix (enfin un peu par moments mais je considère que c'est parce que je ne connais pas bien le langage encore) alors que je peux te dire que Python m'a fait perdre du temps en laissant passer des atrocités que rustc n'aurait jamais accepté. Ce que je gagne en facilité de codage je le perds parce que je me retrouve avec un logiciel qui plante au bout de 3H de calcul pour une histoire de typage.

J'ai aussi besoin d'aller lire la doc' souvent mais ça fait partie de l'apprentissage du langage.

EDIT: je précise, je suis pas foncièrement anti-Python. Je m'en sers pour traiter des stats et faire joujou avec matplotlib et compagnie dans un notebook Jupyter. Par contre, après avoir eu les problèmes susmentionnés dans mon TIPE, je refuse tout bonnement de faire quoi que ce soit d'autre avec. C'est trop chronophage pour moi, j'ai besoin d'un système de types qui m'empêche de faire de la merde.

+1 -0

Comme Grimur, en fait. Il y a des choses qui me pètent les burnes en Rust, mais c’est à l’usage, et ce sont des points relativement avancés. Par exemple, je haaaaaaaaaaais ces putains de macro, je passe plus de temps à en coder une qu’à recopier le code à la main à tous les endroits où j’en ai besoin, c’est abrutissant. Mais voilà, coder ta propre macro, c’est pas un truc que tu fais dans tes premières semaines d’apprentissage du langage.

Au contraire, Python a une réputation de facilité, et je ne doute pas que ce soit un langage que tu apprécies, mais en toute honnêteté, c’est un langage que je déteste. Chaque fois que je me retrouve obligé de mettre les doigts dedans, je m’arrache littéralement les cheveux.

Parce que j’ai des erreurs à l’exécution qui sortent de nulle part. Parce que cette immondice sans nom qu’est le duck typing fait que je n’ai strictement aucun moyen de savoir ce que je peux faire ou non avec tel ou tel objet du code, et je suis obligé de tester au pif et de voir le résultat. Etc.

Bref, c’est un peu insoluble comme question. :) Et je préfère encore coder en C89 qu’en Python. ^^

+2 -0

Si vous y trouvez votre compte, grand bien vous en fasse, mais vous ne pouvez pas me reprocher d'avoir un point de vue radicalement différent du vôtre.

Je pars du principe qu'après plus d'une décennie à développer des logiciels et à me confronter à la réalité du développement de softs (parfois critiques pour les utilisateurs en termes de stabilité), ce n'est pas au développeur de se plier en quatre pour faire ce dont il a besoin du langage mais l'inverse. Et typiquement Rust me semble répondre absolument parfaitement à des problématiques que quasiment personne ne croise dans la vraie vie, ou bien trop rarement, et encore plus rarement sans avoir une compréhension suffisante du problème pour réussir à le résoudre sans qu'un langage ne le force à rentrer dans un carcan dont il n'a pas besoin le reste du temps.

Ce qui intéresse un client ça ne sera jamais que le programme soit threadsafe par construction, mais simplement qu'il marche et soit dispo le plus rapidement possible.

Quand je dis ça je parle bien de problèmes qui font réellement perdre du temps (donc de l'argent) aux éditeurs de logiciels. Bien sûr à un moment je suis aussi passé par le stade "le langage doit m'empêcher de faire des bêtises et son typage doit être aussi parfait que son datamodel", mais l'expérience me dit strictement l'inverse. Aujourd'hui, avec les pratiques modernes de continuous integration, voire plus modernes encore (continuous delivery), un langage comme Rust me semble arriver la fleur au fusil pour repondre aux mêmes problematiques avec 5 ou 10 ans de retard par rapport au besoin, tout en faisant perdre beaucoup trop de temps au développeur pour qu'il puisse être utilisable dans un vrai projet.

Après chacun voit midi à sa porte. Vous appréciez ce langage et je comprends parfaitement pourquoi, mais aujourd'hui, dans mon métier, je le trouve parfaitement impraticable.

Désolé de ne pas chanter ses louanges, il y a quelques mois encore mon discours était totalement différent, mais à un moment donné il faut retourner dans la réalité des gens dont c'est le métier de développer des logiciels. Et Rust s'y trouve être un n-ième langage théoriquement génial mais inutilisable dans la pratique.

Peut-être que je développe des programmes qui ne sont pas corrects ni prouvables, mais au moins je les livre, avec leurs tests, sans regression, et sans me faire chier avec l'autisme du compilateur, en respectant les deadlines et les impératifs clients. Trouvez quelqu'un qui dise la même chose de Rust, et on en reparle.

+2 -3

Peut-être que je développe des programmes qui ne sont pas corrects ni prouvables, mais au moins je les livre, avec leurs tests, sans regression, et sans me faire chier avec l'autisme du compilateur, en respectant les deadlines et les impératifs clients. Trouvez quelqu'un qui dise la même chose de Rust, et on en reparle.

Et bien c'est parce que tes clients sont relativement peu exigeants. Quand ton client veut que ton programme soit prouvé d'une manière ou d'une autre, tu es bien content que ton compilateur t'aide. Quand on voit le nombre de choses qui se basent sur les bibliothèques bas niveau fournies par les systèmes d'exploitation, c'est pas déconnant de vouloir plus de garanties. Par exemple, plein de machines d'imagerie médicale et de systèmes de supervision industriels tournent sur des OS grand public sans aucune garantie sérieuse dessous… C'est pas rassurant.

Et bien c'est parce que tes clients sont relativement peu exigeants. Quand ton client veut que ton programme soit prouvé d'une manière ou d'une autre, tu es bien content que ton compilateur t'aide.

Les clients exigeants réclamant une preuve, ça représente quelle proportion ? En dehors du spatial, de l'aéronautique et du nucléaire (or, ceux-là ont déjà des outils – Ocaml+Coq, Ada – , ils n'ont pas besoin de Rust), quels clients sont exigant ? Tu le dis toi-même, les gens de la santé n'ont pas cette exigence (à tort probablement, mais c'est un autre problème) !

+1 -1

C ou bien C++. Pas vraiment d'autres alternatives.

Tu veux dire qu'avec la multitudes de langages, d'outils qui ont été développé ces dernières années, il n'y a que le c et le c++ utilisables pour cette tâche… Cela me semble bien réducteur. Parce qu'effectivement, les détracteurs du Rust vous semblez plus convaincants que les partisants, je suis un peu perdu du coup :/

+0 -0

Si on en croit cette page Wikipédia, il y a eu six nouveaux langages utilisables pour de la programmation système depuis la création du C++ :

  • Ada (1983), pour lequel il existe un cours sur ZdS ;
  • D (2001), qui ressemble énormément à du C++, mais n’a pas vraiment eu de succès, donc communauté assez faible ;
  • Nim (2008), dont j’entends parler pour la première fois ;
  • Go (2009), que nohar préfère à Rust ;
  • Rust (2012) ;
  • Swift (2014), mais je ne sais pas trop pourquoi ils l’ont mis, il a besoin de toute une surcouche par dessus OS X / iOS pour fonctionner correctement.

Si vous y trouvez votre compte, grand bien vous en fasse, mais vous ne pouvez pas me reprocher d'avoir un point de vue radicalement différent du vôtre.

De la même manière, tu ne peux pas nous reprocher de défendre le nôtre, en particulier quand ton discours à base de « Omagad, je bite rien à Rust et j’aime pas l’utiliser ! » est en train de convaincre GouleFutée d’abandonner avant même d’avoir essayé. ;-)

ce n'est pas au développeur de se plier en quatre pour faire ce dont il a besoin du langage mais l'inverse.

C’est là que, manifestement, tu vois la robe bleue et nous la voyons blanche. Le langage fait justement précisément ce que j’attends de lui ! Prenons un exemple : l’obligation de complétude des filtrages par motifs.

Alors voilà, j’ai un type enum. C’est super pratique, les types enum, j’en utilise plein mes codes. Quand tu fais un filtrage par motifs sur un type enum, il faut fournir un traitement pour toutes les variantes, sinon, le jour où ton utilisateur te balance une variante qui n’est pas prévue, ton programme plante sauvagement. Pas bien.

Seulement voilà, un beau jour, je décide d’ajouter une variante à mon enum, pour gérer un nouveau cas qui n’était pas prévu au départ. Je mets donc à jour toutes les fonctions qui utilisent ce type enum, histoire de ne pas créer moi-même des trous dans mon programme. Et si j’en oublie une, le compilo est vachement sympa, il me prévient !

Ce n’est pas une nuisance, c’est une aide. Je veux obtenir un certain résultat, et le langage est fait de telle manière qu’il m’aide à atteindre ce résultat.

Ce qui intéresse un client ça ne sera jamais que le programme soit threadsafe par construction, mais simplement qu'il marche et soit dispo le plus rapidement possible.

Je ne m’attarderai pas sur le biais évident de cette position. D’une part, parce qu’il n’y a pas que le monde marchand qui produit du logiciel. D’autre part, parce que lorsque se pose la question de la répartition en temps et en argent entre la réalisation première du logiciel et la correction de bogues postérieurement à la livraison, choisir de minimiser la première au mépris des conséquences sur la seconde est très loin d’être une évidence et une décision nécessairement sensée.

Aujourd'hui, avec les pratiques modernes de continuous integration, voire plus modernes encore (continuous delivery), un langage comme Rust me semble arriver la fleur au fusil pour repondre aux mêmes problematiques avec 5 ou 10 ans de retard par rapport au besoin, tout en faisant perdre beaucoup trop de temps au développeur pour qu'il puisse être utilisable dans un vrai projet.

Donc ce que tu es en train de me dire, c’est qu’il vaut mieux envoyer du code à un serveur d’intégration continue, attendre qu’il fasse tourner une batterie complète de tests, et voir à ce moment-là si tout va bien, plutôt que d’avoir un compilateur qui filtre dès le départ une bonne partie des erreurs potentielles ? Que ça, ça fait gagner du temps ? Permets-moi d’être légèrement sceptique…

J’ajouterai deux points qui n’ont pas encore vraiment été abordés. Le premier, c’est que les langages sont plus efficaces pour certaines tâches et moins pour d’autres. J’aime beaucoup Rust, mais quand j’ai besoin de faire du traitement de chaînes de caractères de manière rapide et dégueulasse, je sors Perl du placard. Et inversement, il faudrait être cinglé pour faire de la programmation système en Python.

Or, GouleFutée nous demande des conseils pour de la programmation système. Pas pour de la programmation en générale, pour de la programmation système. Et Rust est un très bon langage pour ça. En particulier pour se former et apprendre une certaine rigueur.

Le second, c’est un point plus général sur la « pureté ». Il y a énormément de choses que l’on peut reprocher à Haskell, et Eusèbe pourra t’expliquer en long en large et en travers pourquoi Haskell n’est pas 100 % pur.

Mais une chose est certaine : une fois que tu as écrit une fonction pure en Haskell, et vérifié qu’elle produit les résultats attendus, tu peux la réutiliser dans absolument n’importe quel autre projet, avec la garantie qu’elle fonctionnera correctement et n’introduira pas de bogue dans un code existant.

Et cette réutilisabilité inconditionnelle du code, c’est clairement quelque chose d’appréciable.

+3 -0

Dominus Carnufex apporte des élements très intéressants et de plus j'en découvre moi-même de nombreux, et notamment la rigueur dont je manque cruellement. Je pense que le Rust mérite que je creuse et que je l'apprenne car je ne veux pas vraiment m'essayer au C/ C++. Merci beaucoup de toutes vos interventions ^^

je ne veux pas vraiment m'essayer au C/ C++

Si tu veux faire de la programmation système, c'est une erreur (soyons clair, « essayer Rust » est différent de « ne pas faire de C », et c'est le second l'erreur ^^ ). Quoi qu'on pense de Rust, une immense majorité des codes de programmation système actuels sont écrits en C ou C++, donc il te faudra bien apprendre le langage (ne serai-ce que pour lire le code des autres ou contribuer). Tu en auras tôt ou tard besoin.

Tu peux préférer commencer par Rust, mais ne te fait pas d'illusions, tu devras apprendre le C/C++ pour faire de la programmation système un jour ou l'autre.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte