en même temps, il écrit bien : j'ai compris son code sans effort et à la première lecture. c'est peut-être pas pour rien que j'ai toujours bien aimé ce langage : je dois être mal câblé :-/
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
C et C++ sont toujours là et doivent toujours lui mettre une grosse fessée niveau perf non?
Pour les classiques micro-benchmarks c'est tout pareil ; tantôt l'un est devant de quelques pourcents, tantôt un autre. En gros si on a le temps et la motivation, on peut être quasi optimal avec C/C++/Rust (et c'est le cas quand ces micro-benchmarks sont écrits : on prend tout le temps d'écrire quelques dizaines de lignes de manière à être optimisé).
Après dans la pratique on a rarement la possibilité de tout optimiser ; et du coup une question plus pertinente est quelle la performance d'un code moyen (parce que dans l'absolu on pourrait tout faire en ASM pour être optimaux ; mais on ne le fait pas pour des raisons évidentes). J'ai bien aimé cet article par exemple qui compare C et Rust (l'auteur dit qu'avec C++ ça serait très légèrement différent): https://kornel.ski/rust-c-speed
Il est Intéressant de lire l'accueil qui lui est fait sur Reddit:
Pas forcément, le sous-reddit en question est celui de Rust, donc les commentaires risquent de refléter une vision du langage Go non fondée sur une expérience typique. Bien qu'il y ait du monde qui utilise vraiment les deux langages, les plus vocaux sont souvent ceux qui utilisent surtout l'un des deux et ont construit une préférence forte pour l'un en fonction de leurs besoins.
En particulier, contrairement à Rust, l'usage d'unsafe en Go est extrêmement rare (en dehors des gens qui écrivent des bindings), donc le commentaire auquel tu fais référence n'a aucun impact statistique. Son côté sarcastique est gratuit : ça illustre juste que son auteur a compris que Go n'est pas Rust et n'a pas pu supporter le choc de cette révélation. Le problème (d'ergonomie) soulevé affecte une partie du langage rarement utilisée et est donc sans aucun impact du point de vue de la courbe d'apprentissage du langage. On peut faire du Go pendant des années sans être confronté à cela, c'est même de loin le cas le plus fréquent.
Je suis en train de tester Go plus intensément qu'avec un hello world. Mes premières impressions:
c'est simple, que ce soit le langage ou l'outillage, même ma grand mère, un bébé 42 ou un prestapute survendu SSIIESN pourrait faire du Go ;
ça compile vite ;
on ne peut pas organiser son code source comme on veut ;
ça manque de généricité, vivement la prochaine version ;
le support (doc, communauté, libs) est bon.
Bref ça peut remplacer Java en entreprise, c'est à dire qu'on ne s'éclate pas, mais qu'on arrive à bosser en équipe, car tout le monde va coder plus ou moins de la même façon avec les mêmes outils.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Exactement : le langage n'a pas été conçu pour être fun, mais pensé dès le départ pour le travail en équipe (d'où le fait qu'on ne peut pas organiser son code comme on veut) et pour être pris en main très rapidement (sans retomber dans les travers du C) tout en étant performant.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
Je ne l'avais pas posté puisque cet article consensuel n'a suscité aucune réaction dans la communauté Go
Pour le reste j'avais lu un autre fil, plutôt intéressant, qui illustrait bien à quel point la simplicité du langage revendiquée déportait implicitement la complexité sur le programmeur lorsqu'il s'agit de passer à l'échelle.
C'était à propos de l'adoption de la généricité à venir qui ne fait pas l'unanimité. Lorsqu'on se met à recopier ad eternam le même code ou contourner au travers de cast le typage statique, on a clairement un souci. Le mantra de la simplicité syntaxique jusqu'á présent est vu comme un frein alors qu'en disposer dans d'autres langages génère de la complexité mais apporte la puissance.
Pas mal d'autres points étaient abordés (le traitement des erreurs évidemment, les goroutines comme unique instrument pour la concurrence, le contre exemple K8S…)
Je ne l'avais pas posté puisque cet article consensuel n'a suscité aucune réaction dans la communauté Go
La communauté Go abrite moins de curieux et passionnés des langages que la communauté Rust, donc ce genre d'articles reçoit moins d'intérêt, surtout vu leur caractère répétitif.
L'article est peut-être consensuel, mais globalement résume l'essentiel. En d'autres termes, bien que parfois les deux peuvent s'appliquer, il n'y a pas de compétition significative entre Rust et Go en pratique. Les articles non consensuels sur le sujet ont souvent tendance à se démener à propos de détails sortis de contexte sans en évaluer l'impact réel en pratique.
Pour ce qui est de la généricité, pas mal de monde est d'accord qu'il existe un certain pourcentage d'applications (peut-être autour de 10% ou 20% ?) qui en bénéficieraient suffisamment pour que ça vaille la peine. Ça concerne suffisamment de monde pour que les développeurs aient décidé d'ajouter ça d'ici une ou deux versions, mais pas assez de monde pour qu'ils l'aient fait dès le départ ni pour qu'ils ajoutent une généricité aussi puissante et complexe que dans d'autres langages.
Dans la plupart des applications, les mécanismes déjà présents de réutilisation (interfaces), suffisent. Pas étonnant qu'un certain nombre de programmeurs Go ne soit pas très excité et n'y voit pas de quoi en faire un fromage. Pour ce type de programmeur Go, qu'on lui dise que son langage est pas bien, car il est pas assez générique (ou autre), ça va le surprendre, il va pas savoir quoi dire. Ça doit se ressentir un peu comme si on te reproche de ne pas automatiser complètement l'installation de ta distrib sur tes machines chez toi; tu répondras que ça va, tu fais pas ça souvent, donc t'as pas envie de te casser la tête et tu le fais deux fois (je parie que même des sysadmins ne prennent pas toujours la peine d'automatiser chez eux ce genre de choses).
Comme pour toute fonctionnalité, chacun a tendance à en évaluer l'intérêt du point de vue des choses qu'il fait, puis attacher des émotions par dessus ça, puis se sentir obligé de les justifier dans l'abstrait. Ça a beau être très consensuel et banal comme explication, je trouve honnêtement que c'est surtout ça qui génère tous ces articles Go vs Rust.
pas assez de monde pour qu'ils l'aient fait dès le départ ni pour qu'ils ajoutent une généricité aussi puissante et complexe que dans d'autres langages
C'est plutôt qu'ils n'ont pas réussi à le faire dès le début?
Ça a été la même chose en Java avec le même pattern de mauvaise foi mon langage est tellement génial que tu n'en as pas besoin qui se transforme bon ok on va le faire pour vous faire plaisir avant de devenir notre langage est maintenant le meilleur grâce à la généricité !.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Posté par anaseto .
Évalué à 2.
Dernière modification le 19 mars 2021 à 18:16.
C'est plutôt qu'ils n'ont pas réussi à le faire dès le début?
Oui, c'est juste que la difficulté n'était pas tant d'ajouter la généricité en soi que le fait de l'ajouter tout en conservant le reste du design qu'ils considéraient prioritaire. Ajouter de la généricité de façon peu orthogonale ou en modifiant certaines parties du langage aurait sans doute été plus facile et faisable avant, mais pas forcément une bonne idée.
Ça a été la même chose en Java avec le même pattern de mauvaise foi mon langage est tellement génial que tu n'en as pas besoin qui se transforme bon ok on va le faire pour vous faire plaisir avant de devenir notre langage est maintenant le meilleur grâce à la généricité !.
Les créateurs de Go ne me donnent pas l'impression de changer de discours comme ça, suivant comme ça les arrange. Mais, oui, il y a aura toujours du monde pour tenir ce genre de discours (un langage populaire attire l'argent, et là où il y a de l'argent se faufilent toujours des charlatans).
Les créateurs du langage s'y connaissent bien en compilateurs et en besoin de programmation système ; de plus ils avaient un cahier des charges bien précis, et le résultat a largement répondu aux attentes (au point de devenir le succès actuel) La comparaison actuelle est fort injuste car les auteurs et les objectifs de l'autre langage sont fort loin de celui-ci ; leur positionnement commercial non plus. Tu fais donc, pour moi, un parallèle qui n'a pas lieu d'être si ce n'est un fantasme.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
Il y a tellement de trucs mal foutus dans Go (l'absence de généricité, les paniques, les variables ombragés, les rondelles de tableaux…) et dans Java (l'absence de structs, l'effaçage de types, les exceptions non signalés) qu'on ne peut exclure un certain degré d'improvisation et de ratage dans leurs développements.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Il y a tellement de trucs mal foutus dans Go (l'absence de généricité, les paniques, les variables ombragés, les rondelles de tableaux…)
Que verrais-tu à la place des panics ? C'est une forme minimale d'exceptions pour les cas vraiment exceptionnels (correspondant à des erreurs de programmation en général : recover n'est utilisé que dans de rares occasions) qu'il est difficile d'éviter : Rust fait un panic aussi par exemple lors d'un accès tableau mal indexé.
Les variables ombragées peuvent en effet parfois conduire à une surprise, c'est indéniable, mais je pense que le choix a été fait en connaissance de cause. Elles sont parfois utiles sur le moment lors de refactoring (ça évite de renommer inutilement des variables) ou juste parce qu'utiliser une variable avec le même nom dans un bloc est intuitif (genre err) et qu'utiliser de la mutation plutôt que du shadowing aurait été encore plus problématique. Cela dit, il y a des outils d'analyse statique qui détectent les variables ombragées, et certains cas typiques sont même détectés de base (par exemple si variable non utilisée, ou variable de retour ombragée avant return).
Pour ce qui est des rondelles de tableau, je ne suis pas sûr de savoir à quoi tu fais référence ;-) Si tu fais référence aux slices, je trouve au contraire que c'est une partie très réussie du langage, donc je serais curieux de savoir ce que tu leur reproches ? Ils ont un côté un peu subtil par rapport à de simples tableaux, mais le concept est puissant et s'inspire à la fois des classiques tableaux dynamiques à la Python ou Perl ainsi de ce que l'on retrouve (sous une forme n-dimensionnelle plus complexe) dans les bibliothèques numériques pour d'autres langages qui permettent de sélectionner des fenêtres/slices.
Merci ; je n'aurais pas mieux dit. Et du coup, je ne vois toujours pas de quelles improvisations il parle mais bon, c'est souvent le cas de ce genre de procès de langages qu'on ne connait pas et qu'on veut absolument comparer dogmatiquement à quelque truc à la mode.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
Si j'étais dogmatique du langage, je ferais encore du C++ qui est toujours bien plus puissant que Java, Go ou même Rust et pas beaucoup plus compliqué au final :-)
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Des exceptions contrôlées comme en Java? Les panics et les exceptions non contrôlés ont le même défaut, il faut deviner là où tu dois les gérer ou comment les éviter…
Cherche panic dans la doc de https://golang.google.cn/pkg/bufio/ : bonjour pour savoir comment faire un code fiable avec des comportements comme Scan panics if the split function returns too many empty tokens without advancing the input.
Ils ont un côté un peu subtil par rapport à de simples tableaux
Je préférais moins subtil et plus fiable du type std::vector.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Ça ce serait en tant que moyen de gestion d'erreurs. En Go le panic n'est pas utilisé pour cela.
Je ne dis pas que l'approche Go avec retours multiples pour la gestion des erreurs est meilleure ou non (c'est assez subjectif, vu le manque de consensus sur le sujet), mais c'est là une autre question. Étant donné le choix fait dans Go pour la gestion d'erreurs, les exceptions contrôlées, une solution complètement différente, conduiraient à une situation plutôt difficile où il faut considérer deux méthodes de gestion d'erreurs lorsqu'on lit du code.
Cherche panic dans la doc de https://golang.google.cn/pkg/bufio/ : bonjour pour savoir comment faire un code fiable avec des comportements comme Scan panics if the split function returns too many empty tokens without advancing the input.
Tel que je comprends la chose, un panic là signifie que la fonction de splitage qu'on a donné est incorrecte. Ça me semble être juste une façon ad hoc d'ajouter une détection de boucle infinie dans Scan (l'heuristique étant 100 itérations sans avancement : ça devrait écarter tous les cas licites en pratique, je ne vois pas trop pourquoi on pourrait avoir un avancement de zéro plus de une ou deux fois). Ce genre de cas d'utilisation de panic est extrêmement rare dans Go.
Je préférais moins subtil et plus fiable du type std::vector.
C'est moins subtil, oui. Fiable, les deux le sont, je dirais.
L'utilisation de slices permet souvent de gérer une fenêtre et donc d'avoir un code avec des indices plus simples (sans gérer d'offsets) et appliquer des fonctions facilement à une partie de tableau seulement. Perso je trouve que la courbe d'apprentissage vaut le coup, mais c'est subjectif. D'habitude on reproche à Go de trop sacrifier en expressivité en vue d'être simple : là on a une exception où un choix a été fait qui complique peut-être un peu la courbe d'apprentissage pour plus d'expressivité :-)
Ce qui est le cas de bon nombre d'exception en java. Tu n'es pas sensé catcherThrowable, Error, Exception ou RuntimeException (les 2 premiers sont à proscrire, les 2 suivants il faudrait être plus spécifique).
Tu es trop troll est cryptique pour être compris par la populasse. Tu reproche à go d'avoir des Panic et tu voudrait que ce soit comme les Exceptions de java hors ça n'a rien à voir. Les Panic correspondent plus aux Errors de java. Je me doute qu'avec ta comprehenssion des langages il n'y a pas besoin de t'expliquer plus pourquoi tu ne catch pas d'Error en java.
Si tu veux une expression de besoin simple: je ne veux pas que mon programme se crashe comme une merde parce que dans méthode Dotrucmuche de la libXXX, Henry a ajouté un if(âge du capitaine > 42)then panic and throw suicide exception before exit(255) sans mettre à jour la doc.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Je ne comprends pas ton besoin. Comment tu veux éviter au niveau du langage que quelqu'un qui comme Henry n'a pas compris comment l'utiliser ni même programmer en général fasse faire n'importe quoi à un programme ? On ne parle pas ici d'erreur subtile à la C difficile à voir au premier coup d'œil, mais d'erreur de débutant en programmation.
Je ne vois par ailleurs pas en quoi Java le résoudrais : c'est pas parce que les exceptions contrôlées existent qu'il n'est pas possible pour Henry d'écrire du code qui lance des exceptions non contrôlées, à commencer par une division par zéro. Et puis Henry peut te faire des trucs pire, comme une boucle infinie, une faille de sécurité ou t'effacer ton $HOME.
Ton besoin « simple » ne me semble pas être résoluble dans un langage généraliste au niveau du langage lui-même. La solution classique pour éviter ce genre de soucis, c'est de reviewer le code d'Henry avant de le merger. Je ne vois pas comment faire autrement.
La première solution est impossible dans un langage généraliste, car dans ces langages, c'est un problème indécidable.
La deuxième solution permet juste de cacher un bug (donc conduisant à un comportement imprévu, potentiellement une faille) tout en ayant un coût en performances (à mon avis pas négligeable, mais à vérifier). Choix favorisant la disponibilité (faire quelque chose à tout prix) contre la correction et les performances. Peut-être raisonnable pour le web.
La troisième, c'est la même qu'un panic avec recover en Go : a priori utilisé uniquement en cas d'erreur vraiment exceptionnelle (le plus souvent provenant d'une erreur de programmation) pour un système où la disponibilité est plus importante que la correction. C'est a priori rattrapé assez près du main, dans le but de relancer le programme ou un sous-système de celui-ci, et pas à chaque division par zéro (autrement le code deviendrait imbitable). Du coup, ça rentre bien dans le cadre des utilisations potentielles de panic/recover. La différence pratique, c'est qu'en Go il y a une distinction au niveau langage entre une situation d'exception (issue d'une erreur de programmation) et une simple erreur à laquelle il est possible de réagir plus spécifiquement.
Posté par barmic 🦦 .
Évalué à 2.
Dernière modification le 22 mars 2021 à 12:22.
La première solution est impossible dans un langage généraliste, car dans ces langages, c'est un problème indécidable.
Si c'est possible, c'est juste que le compilateur t'interdit une division s'il ne peut pas s'assurer que le dénominateur n'est pas 0.
Donc
a = b / c
ne compile pas dans le cas général, il faut écrire des trucs du genre :
a = c != 0 ? b / c : 0
Et oui ça peux devenir relou dans tu as un truc du genre :
Ça t'oblige à déstructurer ton calcul et si le langage et le compilateur sont pas au poil tu peut perdre en performance (il faut qu'il puisse virer les vérification à la compilation pour reconstruire l'opération).
Sachant que de base tout ce qui va cacher pour toi (en attrapant l'interruption ou en faisant la vérification pour toi) va consommer de la ressource.
Ce que tu dis revient juste à étendre la sémantique de la division pour donner un comportement différent à la division par zéro. Au lieu d'un crash, on aurait une valeur particulière, c'est-à-dire grosso-modo la solution numéro 2, sauf qu'en version explicite (écriture explicite de la condition) et potentiellement plus flexible (genre retourner autre chose que zéro si le dénominateur est nul, mais je vois pas trop à quoi ça servirait).
Le compilateur ne pourra essentiellement optimiser que les cas trivaux par propagation de constantes et élimination/réécriture de sous-expressions communes : le plus souvent, la division sera impossible à optimiser. Enlever ces vérifications est un problème indécidable en général et je ne pense pas qu'il y ait d'heuristique efficace pour cela dans un compilateur actuel. Au mieux on peut espérer que le prédicteur de branchement du CPU fera pas trop mal les choses.
Ce que tu dis revient juste à étendre la sémantique de la division pour donner un comportement différent à la division par zéro. Au lieu d'un crash, on aurait une valeur particulière, c'est-à-dire grosso-modo la solution numéro 2, sauf qu'en version explicite (écriture explicite de la condition) et potentiellement plus flexible (genre retourner autre chose que zéro si le dénominateur est nul, mais je vois pas trop à quoi ça servirait).
Pas forcément, là c'était des exemples, mais ça peut être pour afficher des messages d'erreur par exemple. Il n'est pas question la division devienne une fonction totale, mais que tes fonctions qui utilisent la division soient totales. Ça peut d'ailleurs s'implémenter aussi si on considère que la division ne renvoie pas un nombre, mais un type double|NaN qu'il faudra traiter.
Enlever ces vérifications est un problème indécidable en général et je ne pense pas qu'il y ait d'heuristique efficace pour cela dans un compilateur actuel.
Je pense qu'il fera très bien ce que tu lui demande c'est à dire produire un code proche de l'optimal avec les sécurité que tu lui demande. C'est juste que ça peut demander de ne pas laisser le CPU faire un calcul de bout en bout sans vérification intermédiaire.
La première solution est impossible dans un langage généraliste, car dans ces langages, c'est un problème indécidable.
Pourquoi?
La deuxième solution permet juste de cacher un bug
Pourquoi la division par zéro serait plus un bug que la division par 42 ? Pas évident et pourquoi un bug provoquerait systématiquement un crash complet d'un programme?
La différence pratique, c'est qu'en Go il y a une distinction au niveau langage entre une situation d'exception (issue d'une erreur de programmation) et une simple erreur à laquelle il est possible de réagir plus spécifiquement.
Je trouve que cette distinction rends très pénible d'utiliser des bibliothèques: on ne sait jamais si une fonction qu'on appelle peut faire crasher ou non le programme.
C'est aussi une question de pratique: la plupart des bibliothèques C n'utilisent que très rarement un équivalent du panic comme raise(SIGABRT).
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Pourquoi la division par zéro serait plus un bug que la division par 42 ?
Parce qu'elle n'a pas de sens mathématiques. De la même manière que tu n'adresse pas un tableau avec des nombres imaginaires. Le Not A Number n'est qu'une représentation d'une erreur. Tu peux faire des choses avec comme avec une erreur ça n'en est pas moins une erreur.
Il y a plein de résultats qui n'ont pas de sens sans être un bug :-) En tout cas, crasher le programme pour ça c'est souvent trop violent pour l'utilisateur.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
C'est une conséquence du Théorème de Rice. Toute propriété sémantique (non triviale) sur un programme est indécidable. Grosso-modo, non-trivial signifie qu'il existe des programmes qui vérifient la propriété et des programmes qui ne la vérifient pas.
Le théorème s'applique aux langages qui sont Turing-complets, donc en particulier à tous les langages généralistes.
Et comme on en parlait c'est tout à fait possible c'est juste que tu dois exprimer dans ton code cette sémantique. Tu disqualifie un peu vite les choses comme indécidables. Il est tout à fait possible d'écrire un programme qui vérifie qu'aucun dénominateur est égale à 0. Si vraiment tu as besoin de t'en convaincre c'est le même problème que vérifier la nullité des références ou pointeurs.
Ce qui est indécidable c'est de savoir si le cas où le dénominateur est égal à zéro peut se produire ou pas. C'est à cet énoncé que le théorème de Rice s'applique. Ça veut dire qu'en général des checks au runtime devront être ajoutés pour donner une sémantique particulière dans le cas d'un dénominateur nul. Ça peut être fait soit par le compilateur (comme dans Javascript), soit manuellement du fait de contraintes syntaxiques spéciales (ce que tu proposes). La deuxième méthode n'est utilisée dans aucun langage généraliste de base ; la première parfois dans les compilateurs qui n'ont pas de focalisation sur les performances. Dans les deux cas, le problème est le même : aucune garantie que le programme n'a pas de bug et que la branche zéro ne sera pas prise ; au mieux, on peut limiter les dégâts.
Ce qu'on trouve au mieux en pratique, c'est des outils qui font des analyses statiques pour vérifier qu'un code respecte des pratiques particulières (c'est-à-dire utilise un sous-ensemble du langage et pas le langage en général), et lorsque c'est le cas, elles peuvent nous assurent l'absence de division par zéro. C'est le genre d'approche qu'on retrouve dans certains codes critiques.
Ce qui est indécidable c'est de savoir si le cas où le dénominateur est égal à zéro peut se produire ou pas. C'est à cet énoncé que le théorème de Rice s'applique.
Là tu cherche à prouver automatiquement qu'un code ne fera jamais de division par 0 ce qui n'est pas le sujet. Le sujet c'est de gérer le cas d'une division par 0. C'est aussi un sophisme le jusqueboutisme pour invalider ;)
Et oui j'ai bien dis dès mon premier commentaire que ça a un coût.
Ce qu'on trouve au mieux en pratique, c'est des outils qui font des analyses statiques pour vérifier qu'un code respecte des pratiques particulières (c'est-à-dire utilise un sous-ensemble du langage et pas le langage en général), et lorsque c'est le cas, elles peuvent nous assurent l'absence de division par zéro. C'est le genre d'approche qu'on retrouve dans certains codes critiques.
Ou par preuve automatique ou pas écriture par automate (tu écris dans un méta langage qui va produire un code ayant forcément certaines propriétées).
Là tu cherche à prouver automatiquement qu'un code ne fera jamais de division par 0 ce qui n'est pas le sujet. Le sujet c'est de gérer le cas d'une division par 0. C'est aussi un sophisme le jusqueboutisme pour invalider ;)
J'avoue ne pas être sûr de ce qu'entendait devnewton à l'origine par « la détecter à la compilation ». J'ai imaginé que « la » faisait référence à « la division par zéro » qu'il faudrait alors gérer. J'ai pas imaginé qu'il parlait de détecter n'importe quelle division (facile), mais ton interprétation moins littérale est plus raisonnable. Après, aucun compilateur mainstream ne fait ça non plus que je sache (même si pour le coup c'est possible).
Les seuls patterns qui pourraient surprendre quand on vient d'autres langages c'est try/catch/finally et le vieux pattern Try-Get (comme int.TryParse), et le mot clé (optionnel) pour filtrer les exceptions : when
Depuis C# 8 y'a l'option d'activer les Nullable Reference Types, mais c'est juste le compilateur qui vérifie pour toi si tu as bien vérifié et évité null partout et que tu as mis des annotations (ça reprend la même que pour les bons vieux nullable, comme int? à la place de int).
Mais c'est autre chose. Disons que ça aide à combattre les NullReferenceException, et c'est pas trop tôt (en F# NULL ça n'existe pas et il s'en sort pas si mal :p ).
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
Pour le reste:
- Y'a des structs, enums, et tout ça, pas de problème.
- La généricité n'utilise pas l'écrasement des types. C'est beaucoup plus pratique.
Ça permet notamment des filtres sur les méthodes génériques, du genre where T : new() ou where T : IBidule…
Super pratique quand tu as besoin d'avoir un comportement spécifique par type plutôt que de mettre des if moches.
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
Super pratique quand tu as besoin d'avoir un comportement spécifique par type plutôt que de mettre des if moches.
Je suis pas sûr que ce soit bien sans sealed class ce qui est entrain d'arriver dans java.
Mais je suis d'accord que le type erasure pose problème par exemple si on veut construire un objet de la classe du type effectif de ta méthode. C'est pour ça que l'on passe la classe à ce genre de méthode :
Aa=build(A.class);
Par contre, c'est pas mal mitigé avec l'utilisation de lambda (pas dans tous les cas, mais dans une partie).
Mais oui C# qui a implémenté les génériques un an après java est mieux sur ce point là. Je pense que c'est dû au fait qu'ils ont implémenté la généricité dans la vm là où sun se l'ai interdit (probablement pour ne pas casser l'écosystème des jvms qui était foisonnant à l'époque).
# Ouaiche
Posté par El Titi . Évalué à 4.
Article écrit par une personne impliquée dans le dev de Go.
Il est Intéressant de lire l'accueil qui lui est fait sur Reddit:
https://www.reddit.com/r/rust/comments/m3yhed/rust_vs_go_why_theyre_better_together_the_new/
et notamment ce commentaire qui met bien exergue, que la "prétendue" simplicité de Go est à double tranchant:
https://www.reddit.com/r/rust/comments/m3yhed/rust_vs_go_why_theyre_better_together_the_new/gqs8ocp?utm_source=share&utm_medium=web2x&context=3
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 4.
C et C++ sont toujours là et doivent toujours lui mettre une grosse fessée niveau perf non?
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par El Titi . Évalué à 5.
Voilà un article fouillé qui ne se contente pas de reprendre des citations en guise d'argumentaire:
https://benhoyt.com/writings/count-words/
[^] # Re: Ouaiche
Posté par Glandos . Évalué à 2.
Je découvre Forth C'est… spécial. Et comme il le dit :
[^] # Re: Ouaiche
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 1.
en même temps, il écrit bien : j'ai compris son code sans effort et à la première lecture. c'est peut-être pas pour rien que j'ai toujours bien aimé ce langage : je dois être mal câblé
:-/
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Ouaiche
Posté par kreako . Évalué à -1.
"toujours" ? Ce n'est pas le cas.
Contre-exemple, facile mais concret d'une application bien utile : rg (rust) met une grosse fessée déculottée à grep (c).
[^] # Re: Ouaiche
Posté par lolop (site web personnel) . Évalué à 10.
rg
vsgrep
, c'est une comparaison de langages ou d'implementations algorithmiques ?Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 5.
toujours(3) pas toujours(4) https://fr.wiktionary.org/wiki/toujours
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par GuieA_7 (site web personnel) . Évalué à 2.
Pour les classiques micro-benchmarks c'est tout pareil ; tantôt l'un est devant de quelques pourcents, tantôt un autre. En gros si on a le temps et la motivation, on peut être quasi optimal avec C/C++/Rust (et c'est le cas quand ces micro-benchmarks sont écrits : on prend tout le temps d'écrire quelques dizaines de lignes de manière à être optimisé).
Après dans la pratique on a rarement la possibilité de tout optimiser ; et du coup une question plus pertinente est quelle la performance d'un code moyen (parce que dans l'absolu on pourrait tout faire en ASM pour être optimaux ; mais on ne le fait pas pour des raisons évidentes). J'ai bien aimé cet article par exemple qui compare C et Rust (l'auteur dit qu'avec C++ ça serait très légèrement différent):
https://kornel.ski/rust-c-speed
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 5.
Pas forcément, le sous-reddit en question est celui de Rust, donc les commentaires risquent de refléter une vision du langage Go non fondée sur une expérience typique. Bien qu'il y ait du monde qui utilise vraiment les deux langages, les plus vocaux sont souvent ceux qui utilisent surtout l'un des deux et ont construit une préférence forte pour l'un en fonction de leurs besoins.
En particulier, contrairement à Rust, l'usage d'unsafe en Go est extrêmement rare (en dehors des gens qui écrivent des bindings), donc le commentaire auquel tu fais référence n'a aucun impact statistique. Son côté sarcastique est gratuit : ça illustre juste que son auteur a compris que Go n'est pas Rust et n'a pas pu supporter le choc de cette révélation. Le problème (d'ergonomie) soulevé affecte une partie du langage rarement utilisée et est donc sans aucun impact du point de vue de la courbe d'apprentissage du langage. On peut faire du Go pendant des années sans être confronté à cela, c'est même de loin le cas le plus fréquent.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 7.
Je suis en train de tester Go plus intensément qu'avec un hello world. Mes premières impressions:
SSIIESN pourrait faire du Go ;Bref ça peut remplacer Java en entreprise, c'est à dire qu'on ne s'éclate pas, mais qu'on arrive à bosser en équipe, car tout le monde va coder plus ou moins de la même façon avec les mêmes outils.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 1.
Exactement : le langage n'a pas été conçu pour être fun, mais pensé dès le départ pour le travail en équipe (d'où le fait qu'on ne peut pas organiser son code comme on veut) et pour être pris en main très rapidement (sans retomber dans les travers du C) tout en étant performant.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Ouaiche
Posté par aiolos . Évalué à 3.
T'es obligé d'insulter un pan entier de la profession ?
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 5.
Pardon aux prostitués, je respecte votre dur métier.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par El Titi . Évalué à 5.
Tu as raison. Rendons à César ce qui est à César:
https://www.reddit.com/r/golang/comments/m48zca/rust_vs_go_why_theyre_better_together/
Je ne l'avais pas posté puisque cet article consensuel n'a suscité aucune réaction dans la communauté Go
Pour le reste j'avais lu un autre fil, plutôt intéressant, qui illustrait bien à quel point la simplicité du langage revendiquée déportait implicitement la complexité sur le programmeur lorsqu'il s'agit de passer à l'échelle.
C'était à propos de l'adoption de la généricité à venir qui ne fait pas l'unanimité. Lorsqu'on se met à recopier ad eternam le même code ou contourner au travers de cast le typage statique, on a clairement un souci. Le mantra de la simplicité syntaxique jusqu'á présent est vu comme un frein alors qu'en disposer dans d'autres langages génère de la complexité mais apporte la puissance.
Pas mal d'autres points étaient abordés (le traitement des erreurs évidemment, les goroutines comme unique instrument pour la concurrence, le contre exemple K8S…)
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 4.
La communauté Go abrite moins de curieux et passionnés des langages que la communauté Rust, donc ce genre d'articles reçoit moins d'intérêt, surtout vu leur caractère répétitif.
L'article est peut-être consensuel, mais globalement résume l'essentiel. En d'autres termes, bien que parfois les deux peuvent s'appliquer, il n'y a pas de compétition significative entre Rust et Go en pratique. Les articles non consensuels sur le sujet ont souvent tendance à se démener à propos de détails sortis de contexte sans en évaluer l'impact réel en pratique.
Pour ce qui est de la généricité, pas mal de monde est d'accord qu'il existe un certain pourcentage d'applications (peut-être autour de 10% ou 20% ?) qui en bénéficieraient suffisamment pour que ça vaille la peine. Ça concerne suffisamment de monde pour que les développeurs aient décidé d'ajouter ça d'ici une ou deux versions, mais pas assez de monde pour qu'ils l'aient fait dès le départ ni pour qu'ils ajoutent une généricité aussi puissante et complexe que dans d'autres langages.
Dans la plupart des applications, les mécanismes déjà présents de réutilisation (interfaces), suffisent. Pas étonnant qu'un certain nombre de programmeurs Go ne soit pas très excité et n'y voit pas de quoi en faire un fromage. Pour ce type de programmeur Go, qu'on lui dise que son langage est pas bien, car il est pas assez générique (ou autre), ça va le surprendre, il va pas savoir quoi dire. Ça doit se ressentir un peu comme si on te reproche de ne pas automatiser complètement l'installation de ta distrib sur tes machines chez toi; tu répondras que ça va, tu fais pas ça souvent, donc t'as pas envie de te casser la tête et tu le fais deux fois (je parie que même des sysadmins ne prennent pas toujours la peine d'automatiser chez eux ce genre de choses).
Comme pour toute fonctionnalité, chacun a tendance à en évaluer l'intérêt du point de vue des choses qu'il fait, puis attacher des émotions par dessus ça, puis se sentir obligé de les justifier dans l'abstrait. Ça a beau être très consensuel et banal comme explication, je trouve honnêtement que c'est surtout ça qui génère tous ces articles Go vs Rust.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 7.
C'est plutôt qu'ils n'ont pas réussi à le faire dès le début?
Ça a été la même chose en Java avec le même pattern de mauvaise foi mon langage est tellement génial que tu n'en as pas besoin qui se transforme bon ok on va le faire pour vous faire plaisir avant de devenir notre langage est maintenant le meilleur grâce à la généricité !.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 2. Dernière modification le 19 mars 2021 à 18:16.
Oui, c'est juste que la difficulté n'était pas tant d'ajouter la généricité en soi que le fait de l'ajouter tout en conservant le reste du design qu'ils considéraient prioritaire. Ajouter de la généricité de façon peu orthogonale ou en modifiant certaines parties du langage aurait sans doute été plus facile et faisable avant, mais pas forcément une bonne idée.
Les créateurs de Go ne me donnent pas l'impression de changer de discours comme ça, suivant comme ça les arrange. Mais, oui, il y a aura toujours du monde pour tenir ce genre de discours (un langage populaire attire l'argent, et là où il y a de l'argent se faufilent toujours des charlatans).
[^] # Re: Ouaiche
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à -1.
Les créateurs du langage s'y connaissent bien en compilateurs et en besoin de programmation système ; de plus ils avaient un cahier des charges bien précis, et le résultat a largement répondu aux attentes (au point de devenir le succès actuel) La comparaison actuelle est fort injuste car les auteurs et les objectifs de l'autre langage sont fort loin de celui-ci ; leur positionnement commercial non plus. Tu fais donc, pour moi, un parallèle qui n'a pas lieu d'être si ce n'est un fantasme.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 2.
Tu parles de Go ou de Java ? :-)
Il y a tellement de trucs mal foutus dans Go (l'absence de généricité, les paniques, les variables ombragés, les rondelles de tableaux…) et dans Java (l'absence de structs, l'effaçage de types, les exceptions non signalés) qu'on ne peut exclure un certain degré d'improvisation et de ratage dans leurs développements.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 3.
Que verrais-tu à la place des panics ? C'est une forme minimale d'exceptions pour les cas vraiment exceptionnels (correspondant à des erreurs de programmation en général : recover n'est utilisé que dans de rares occasions) qu'il est difficile d'éviter : Rust fait un panic aussi par exemple lors d'un accès tableau mal indexé.
Les variables ombragées peuvent en effet parfois conduire à une surprise, c'est indéniable, mais je pense que le choix a été fait en connaissance de cause. Elles sont parfois utiles sur le moment lors de refactoring (ça évite de renommer inutilement des variables) ou juste parce qu'utiliser une variable avec le même nom dans un bloc est intuitif (genre
err
) et qu'utiliser de la mutation plutôt que du shadowing aurait été encore plus problématique. Cela dit, il y a des outils d'analyse statique qui détectent les variables ombragées, et certains cas typiques sont même détectés de base (par exemple si variable non utilisée, ou variable de retour ombragée avant return).Pour ce qui est des rondelles de tableau, je ne suis pas sûr de savoir à quoi tu fais référence ;-) Si tu fais référence aux slices, je trouve au contraire que c'est une partie très réussie du langage, donc je serais curieux de savoir ce que tu leur reproches ? Ils ont un côté un peu subtil par rapport à de simples tableaux, mais le concept est puissant et s'inspire à la fois des classiques tableaux dynamiques à la Python ou Perl ainsi de ce que l'on retrouve (sous une forme n-dimensionnelle plus complexe) dans les bibliothèques numériques pour d'autres langages qui permettent de sélectionner des fenêtres/slices.
[^] # Re: Ouaiche
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à -1.
Merci ; je n'aurais pas mieux dit. Et du coup, je ne vois toujours pas de quelles improvisations il parle mais bon, c'est souvent le cas de ce genre de procès de langages qu'on ne connait pas et qu'on veut absolument comparer dogmatiquement à quelque truc à la mode.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3. Dernière modification le 21 mars 2021 à 23:03.
Si j'étais dogmatique du langage, je ferais encore du C++ qui est toujours bien plus puissant que Java, Go ou même Rust et pas beaucoup plus compliqué au final :-)
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 4.
Des exceptions contrôlées comme en Java? Les panics et les exceptions non contrôlés ont le même défaut, il faut deviner là où tu dois les gérer ou comment les éviter…
Cherche panic dans la doc de https://golang.google.cn/pkg/bufio/ : bonjour pour savoir comment faire un code fiable avec des comportements comme Scan panics if the split function returns too many empty tokens without advancing the input.
Je préférais moins subtil et plus fiable du type std::vector.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 3.
Ça ce serait en tant que moyen de gestion d'erreurs. En Go le panic n'est pas utilisé pour cela.
Je ne dis pas que l'approche Go avec retours multiples pour la gestion des erreurs est meilleure ou non (c'est assez subjectif, vu le manque de consensus sur le sujet), mais c'est là une autre question. Étant donné le choix fait dans Go pour la gestion d'erreurs, les exceptions contrôlées, une solution complètement différente, conduiraient à une situation plutôt difficile où il faut considérer deux méthodes de gestion d'erreurs lorsqu'on lit du code.
Tel que je comprends la chose, un panic là signifie que la fonction de splitage qu'on a donné est incorrecte. Ça me semble être juste une façon ad hoc d'ajouter une détection de boucle infinie dans Scan (l'heuristique étant 100 itérations sans avancement : ça devrait écarter tous les cas licites en pratique, je ne vois pas trop pourquoi on pourrait avoir un avancement de zéro plus de une ou deux fois). Ce genre de cas d'utilisation de panic est extrêmement rare dans Go.
C'est moins subtil, oui. Fiable, les deux le sont, je dirais.
L'utilisation de slices permet souvent de gérer une fenêtre et donc d'avoir un code avec des indices plus simples (sans gérer d'offsets) et appliquer des fonctions facilement à une partie de tableau seulement. Perso je trouve que la courbe d'apprentissage vaut le coup, mais c'est subjectif. D'habitude on reproche à Go de trop sacrifier en expressivité en vue d'être simple : là on a une exception où un choix a été fait qui complique peut-être un peu la courbe d'apprentissage pour plus d'expressivité :-)
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 4.
Oui c'est une pas gestion d'erreur: on crashe le programme salement.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 3.
Ce qui est le cas de bon nombre d'exception en java. Tu n'es pas sensé catcher
Throwable
,Error
,Exception
ouRuntimeException
(les 2 premiers sont à proscrire, les 2 suivants il faudrait être plus spécifique).https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
J'en parlais là :-)
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 2.
Tu es trop troll est cryptique pour être compris par la populasse. Tu reproche à go d'avoir des Panic et tu voudrait que ce soit comme les Exceptions de java hors ça n'a rien à voir. Les Panic correspondent plus aux Errors de java. Je me doute qu'avec ta comprehenssion des langages il n'y a pas besoin de t'expliquer plus pourquoi tu ne catch pas d'Error en java.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
Si tu veux une expression de besoin simple: je ne veux pas que mon programme se crashe comme une merde parce que dans méthode
Dotrucmuche
de lalibXXX
, Henry a ajouté unif(âge du capitaine > 42)then panic and throw suicide exception before exit(255)
sans mettre à jour la doc.Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 2.
Je ne comprends pas ton besoin. Comment tu veux éviter au niveau du langage que quelqu'un qui comme Henry n'a pas compris comment l'utiliser ni même programmer en général fasse faire n'importe quoi à un programme ? On ne parle pas ici d'erreur subtile à la C difficile à voir au premier coup d'œil, mais d'erreur de débutant en programmation.
Je ne vois par ailleurs pas en quoi Java le résoudrais : c'est pas parce que les exceptions contrôlées existent qu'il n'est pas possible pour Henry d'écrire du code qui lance des exceptions non contrôlées, à commencer par une division par zéro. Et puis Henry peut te faire des trucs pire, comme une boucle infinie, une faille de sécurité ou t'effacer ton
$HOME
.Ton besoin « simple » ne me semble pas être résoluble dans un langage généraliste au niveau du langage lui-même. La solution classique pour éviter ce genre de soucis, c'est de reviewer le code d'Henry avant de le merger. Je ne vois pas comment faire autrement.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
La division par zéro c'est un très bon exemple: un programme ne doit pas crasher juste pour ça.
Il y a plusieurs solutions:
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 2.
La première solution est impossible dans un langage généraliste, car dans ces langages, c'est un problème indécidable.
La deuxième solution permet juste de cacher un bug (donc conduisant à un comportement imprévu, potentiellement une faille) tout en ayant un coût en performances (à mon avis pas négligeable, mais à vérifier). Choix favorisant la disponibilité (faire quelque chose à tout prix) contre la correction et les performances. Peut-être raisonnable pour le web.
La troisième, c'est la même qu'un panic avec recover en Go : a priori utilisé uniquement en cas d'erreur vraiment exceptionnelle (le plus souvent provenant d'une erreur de programmation) pour un système où la disponibilité est plus importante que la correction. C'est a priori rattrapé assez près du main, dans le but de relancer le programme ou un sous-système de celui-ci, et pas à chaque division par zéro (autrement le code deviendrait imbitable). Du coup, ça rentre bien dans le cadre des utilisations potentielles de panic/recover. La différence pratique, c'est qu'en Go il y a une distinction au niveau langage entre une situation d'exception (issue d'une erreur de programmation) et une simple erreur à laquelle il est possible de réagir plus spécifiquement.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 2. Dernière modification le 22 mars 2021 à 12:22.
Si c'est possible, c'est juste que le compilateur t'interdit une division s'il ne peut pas s'assurer que le dénominateur n'est pas 0.
Donc
ne compile pas dans le cas général, il faut écrire des trucs du genre :
Et oui ça peux devenir relou dans tu as un truc du genre :
Ça t'oblige à déstructurer ton calcul et si le langage et le compilateur sont pas au poil tu peut perdre en performance (il faut qu'il puisse virer les vérification à la compilation pour reconstruire l'opération).
Sachant que de base tout ce qui va cacher pour toi (en attrapant l'interruption ou en faisant la vérification pour toi) va consommer de la ressource.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 3.
Ce que tu dis revient juste à étendre la sémantique de la division pour donner un comportement différent à la division par zéro. Au lieu d'un crash, on aurait une valeur particulière, c'est-à-dire grosso-modo la solution numéro 2, sauf qu'en version explicite (écriture explicite de la condition) et potentiellement plus flexible (genre retourner autre chose que zéro si le dénominateur est nul, mais je vois pas trop à quoi ça servirait).
Le compilateur ne pourra essentiellement optimiser que les cas trivaux par propagation de constantes et élimination/réécriture de sous-expressions communes : le plus souvent, la division sera impossible à optimiser. Enlever ces vérifications est un problème indécidable en général et je ne pense pas qu'il y ait d'heuristique efficace pour cela dans un compilateur actuel. Au mieux on peut espérer que le prédicteur de branchement du CPU fera pas trop mal les choses.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 2.
Pas forcément, là c'était des exemples, mais ça peut être pour afficher des messages d'erreur par exemple. Il n'est pas question la division devienne une fonction totale, mais que tes fonctions qui utilisent la division soient totales. Ça peut d'ailleurs s'implémenter aussi si on considère que la division ne renvoie pas un nombre, mais un type double|NaN qu'il faudra traiter.
Je pense qu'il fera très bien ce que tu lui demande c'est à dire produire un code proche de l'optimal avec les sécurité que tu lui demande. C'est juste que ça peut demander de ne pas laisser le CPU faire un calcul de bout en bout sans vérification intermédiaire.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
Je viens de voir que le langage Crystal a une approche mixte avec deux opérateurs:
https://crystal-lang.org/reference/syntax_and_semantics/operators.html#multiplicative
https://github.com/crystal-lang/crystal/blob/master/spec/std/int_spec.cr#L456
https://github.com/crystal-lang/crystal/blob/master/spec/std/int_spec.cr#L508
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 2.
Pourquoi?
Pourquoi la division par zéro serait plus un bug que la division par 42 ? Pas évident et pourquoi un bug provoquerait systématiquement un crash complet d'un programme?
Je trouve que cette distinction rends très pénible d'utiliser des bibliothèques: on ne sait jamais si une fonction qu'on appelle peut faire crasher ou non le programme.
C'est aussi une question de pratique: la plupart des bibliothèques C n'utilisent que très rarement un équivalent du panic comme raise(SIGABRT).
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 2.
Parce qu'elle n'a pas de sens mathématiques. De la même manière que tu n'adresse pas un tableau avec des nombres imaginaires. Le Not A Number n'est qu'une représentation d'une erreur. Tu peux faire des choses avec comme avec une erreur ça n'en est pas moins une erreur.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
Il y a plein de résultats qui n'ont pas de sens sans être un bug :-) En tout cas, crasher le programme pour ça c'est souvent trop violent pour l'utilisateur.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 2.
C'est une conséquence du Théorème de Rice. Toute propriété sémantique (non triviale) sur un programme est indécidable. Grosso-modo, non-trivial signifie qu'il existe des programmes qui vérifient la propriété et des programmes qui ne la vérifient pas.
Le théorème s'applique aux langages qui sont Turing-complets, donc en particulier à tous les langages généralistes.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 3.
Et comme on en parlait c'est tout à fait possible c'est juste que tu dois exprimer dans ton code cette sémantique. Tu disqualifie un peu vite les choses comme indécidables. Il est tout à fait possible d'écrire un programme qui vérifie qu'aucun dénominateur est égale à 0. Si vraiment tu as besoin de t'en convaincre c'est le même problème que vérifier la nullité des références ou pointeurs.
Du coup le théorème de Rice ne s'applique pas.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 3.
Ce qui est indécidable c'est de savoir si le cas où le dénominateur est égal à zéro peut se produire ou pas. C'est à cet énoncé que le théorème de Rice s'applique. Ça veut dire qu'en général des checks au runtime devront être ajoutés pour donner une sémantique particulière dans le cas d'un dénominateur nul. Ça peut être fait soit par le compilateur (comme dans Javascript), soit manuellement du fait de contraintes syntaxiques spéciales (ce que tu proposes). La deuxième méthode n'est utilisée dans aucun langage généraliste de base ; la première parfois dans les compilateurs qui n'ont pas de focalisation sur les performances. Dans les deux cas, le problème est le même : aucune garantie que le programme n'a pas de bug et que la branche zéro ne sera pas prise ; au mieux, on peut limiter les dégâts.
Ce qu'on trouve au mieux en pratique, c'est des outils qui font des analyses statiques pour vérifier qu'un code respecte des pratiques particulières (c'est-à-dire utilise un sous-ensemble du langage et pas le langage en général), et lorsque c'est le cas, elles peuvent nous assurent l'absence de division par zéro. C'est le genre d'approche qu'on retrouve dans certains codes critiques.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 3.
Là tu cherche à prouver automatiquement qu'un code ne fera jamais de division par 0 ce qui n'est pas le sujet. Le sujet c'est de gérer le cas d'une division par 0. C'est aussi un sophisme le jusqueboutisme pour invalider ;)
Et oui j'ai bien dis dès mon premier commentaire que ça a un coût.
Ou par preuve automatique ou pas écriture par automate (tu écris dans un méta langage qui va produire un code ayant forcément certaines propriétées).
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 2.
J'avoue ne pas être sûr de ce qu'entendait devnewton à l'origine par « la détecter à la compilation ». J'ai imaginé que « la » faisait référence à « la division par zéro » qu'il faudrait alors gérer. J'ai pas imaginé qu'il parlait de détecter n'importe quelle division (facile), mais ton interprétation moins littérale est plus raisonnable. Après, aucun compilateur mainstream ne fait ça non plus que je sache (même si pour le coup c'est possible).
[^] # Re: Ouaiche
Posté par anaseto . Évalué à 3.
Beaucoup de fonctions de la bibliothèque C font faire (au mieux) un segfault si mal utilisées : c'est l'équivalent du panic en pire.
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
Oui, mais ce n'est pas volontaire :-)
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par xcomcmdr . Évalué à 2.
C# corrige tout ça et plus et est libre et multi-plateforme.
F# est pas mal non plus.
Just sayin'. :)
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 4.
Pour les exceptions en C# je ne m'en souviens pas. Ça a changé? https://www.artima.com/articles/the-trouble-with-checked-exceptions
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par xcomcmdr . Évalué à 2. Dernière modification le 22 mars 2021 à 08:27.
Y'a pas de checked exceptions, ni de throwable ni de errors (j'ai pas regardé ce que c'était en Java, mais en C# ça n'existe pas).
Y'a juste de bonnes vieilles exceptions. Et c'est absolument tout:
https://docs.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions
Les seuls patterns qui pourraient surprendre quand on vient d'autres langages c'est try/catch/finally et le vieux pattern Try-Get (comme int.TryParse), et le mot clé (optionnel) pour filtrer les exceptions : when
Depuis C# 8 y'a l'option d'activer les Nullable Reference Types, mais c'est juste le compilateur qui vérifie pour toi si tu as bien vérifié et évité null partout et que tu as mis des annotations (ça reprend la même que pour les bons vieux nullable, comme int? à la place de int).
Mais c'est autre chose. Disons que ça aide à combattre les NullReferenceException, et c'est pas trop tôt (en F# NULL ça n'existe pas et il s'en sort pas si mal :p ).
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Ouaiche
Posté par xcomcmdr . Évalué à 2.
Pour le reste:
- Y'a des structs, enums, et tout ça, pas de problème.
- La généricité n'utilise pas l'écrasement des types. C'est beaucoup plus pratique.
Ça permet notamment des filtres sur les méthodes génériques, du genre where T : new() ou where T : IBidule…
Super pratique quand tu as besoin d'avoir un comportement spécifique par type plutôt que de mettre des if moches.
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Ouaiche
Posté par devnewton 🍺 (site web personnel) . Évalué à 5.
N'hésite pas à faire une dépêche ou un journal sur C#, je pense qu'on est nombreux à ne pas avoir suivi les évolutions de ce langage.
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 3.
Les nouveautés de 2004 ?
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Ouaiche
Posté par xcomcmdr . Évalué à 2.
Je veux bien présenter tout le langage, mais pour les structs c'est C# 1.0 (2002) et les génériques c'est C# 2.0 (2004). :)
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Ouaiche
Posté par barmic 🦦 . Évalué à 4.
Je suis pas sûr que ce soit bien sans sealed class ce qui est entrain d'arriver dans java.
Mais je suis d'accord que le type erasure pose problème par exemple si on veut construire un objet de la classe du type effectif de ta méthode. C'est pour ça que l'on passe la classe à ce genre de méthode :
Par contre, c'est pas mal mitigé avec l'utilisation de lambda (pas dans tous les cas, mais dans une partie).
Mais oui C# qui a implémenté les génériques un an après java est mieux sur ce point là. Je pense que c'est dû au fait qu'ils ont implémenté la généricité dans la vm là où sun se l'ai interdit (probablement pour ne pas casser l'écosystème des jvms qui était foisonnant à l'époque).
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.