Liste de tous les languages à apprendre pour avoir une vision global de tous les paradigmes

a marqué ce sujet comme résolu.

Je m’insère dans la castagne.

En dehors du côté niche (très large) du VHDL, il apporte aussi un aspect de la programmation qui est rarement mis en avant: il introduit à la programmation synchrone. Il n’y a pas de séquencement des instructions, elles se produisent toutes en même lors du tick de l’horloge. Les langages synchrones comme Lustre ou Esterel sont très utilisés dans l’embarqué. Et VHDL permet de se frotter à la notion facilement.

Sur l’argument de niche d’Eusebe, entre Coq et VHDL, je considère clairement Coq plus une niche que VHDL. Dans beaucoup de cursus, les élèves vont faire un peu de VHDL et/ou en entendre parler. Alors que Coq, lolilol.

Edit: ca peut être l’occasion d’un tuto pour mettre les choses au clair. qui est partant ?

+4 -0

Sans vouloir rentrer dans le débat sur les langages, je conseillerai au PO de ne pas s’intéresser qu’aux langages. Avoir une bonne vue d’ensemble des paradigmes existant c’est bien mais dans la vrai vie on utilise rarement un langage seul et, surtout, il y a beaucoup d’autres choses à connaitre que les langages en soit. Je pense par exemple à la programmation parallèle, asynchrone, les bases de données, la communication réseau, le calcul numérique, etc. Ce sont des exemples de thématiques qui ne sont pas lié à un langage mais qui peuvent être intéressant de connaitre.

Sincèrement "connaitre" 6 langages différent n’est pas spécialement le plus utile, la culture et la connaissance des thématiques est aussi important.

Eusèbe, ce n’est pas parce que tu as un avis sur les langages que c’est forcément LA réponse.

C’est effectivement littéralement ce que j’ai écrit dans mon premier message.

Pour le VHDL, l’argument du synchrone tient la route. Je le rajouterais dans la liste des choses un peu exotiques.

Edit: ca peut être l’occasion d’un tuto pour mettre les choses au clair. qui est partant ?

L’idée est bonne sur le papier, mais honnêtement je pense qu’elle a assez peu de chances d’aboutir à quelque chose d’utile (et d’ailleurs ça n’a jamais rien donné d’intéressant les 42 fois où quelqu’un a essayé).

Donc j’apprend le C en parallèle, ce qui est au fond parfaitement logique, j’ai encore jamais vu un noyau d’OS être codé […], ni en Rust, […] !

AlexandreDeMoura

Loupé : https://www.tockos.org/documentation/getting-started . Et putain, si, ce serait logique de ne plus utiliser C pour développer dans des couches basses, mais plutôt quelque chose comme Rust. Mais il y a encore du travail pour avoir une gestion fine des horreurs nécessaires au développement low-level, pour perdre la sûreté plus sélectivement (voir du côté par exemple des attributs de désactivation de C++ core guideline library).

Ah non pas "loupé", une grande partie des OS ont un noyau codé en C, donc tu m’excuseras, mais quand je voudrais étudier des cas concrêt je ne pense pas que je vais me pencher sur "Tock Embedded Operation Systems".

Et si tu aurais lu mes messages, j’apprend avec le livre de Tanenbaum et même si il fait une apparté sur le C++, la plupart des OS qu’il traite son codé en C.

En ce qui concerne la programmation asynchrone, parallèle etc… Je sais ce qu’est la programmation parallèle, Tanenbaum en parlait sur le chapitre des Threads et des multiprocesseur, donc je compte tenter un peu ça aussi. Je sais juste pas dans quel language m’y mettre. Les bases de données, je m’y connait vraiment pas trop, j’avais prévu de me pencher sur SQL un jour ou l’autre, c’est en rapport ? A ce niveau là, je suis un peu perdu, d’ailleurs si vous avez des tutos à me proposer je vous en serais reconnaissant. J’en trouverais bien sur Google, mais c’est dur d’évaluer la qualité d’un cour quand on maitrise pas le sujet :/

+1 -1

C, C++, C#, Swift, Python, Rubis, Ocaml, Rust, Haskell, Prolog, Erlang, Javascript, D, Go, VBA, Matlab, R, VHDL, Kotlin, Elexir, Coq

Je suis déçu, je m’attendais à une liste beaucoup plus longue au bout d’une page (il manque au moins Perl, Java, Pascal, COBOL, Ada edit : et Lisp). :-°

Sinon, plus sérieusement, personne ne conseille l’Assembleur ? Je pense que cela reste une partie non négligeable pour avoir une vision globale de la programmation. ;)

+1 -0

Je suis déçu, je m’attendais à une liste beaucoup plus longue au bout d’une page (il manque au moins Perl, Java, Pascal, COBOL, Ada edit : et Lisp). :-°

Sinon, plus sérieusement, personne ne conseille l’Assembleur ? Je pense que cela reste une partie non négligeable pour avoir une vision globale de la programmation. ;)

Taurre

Han !!

De la même façon, personne n’a parlé de l’assembleur, même pour le troll #Déception.

Eskimon
+0 -0

À toutes fins utiles, je précise que je ne troll pas pour l’Assembleur. ;)

C’est le cas pour absolument tous les langages. Le C n’est pas facile ni rapide à maîtriser, mais ça reste un des langages qu’on peut maîtriser le plus rapidement, même si ça n’est pas de la tarte. C’était particulièrement vrai avant qu’ils ne tentent d’introduire un modèle mémoire (qui est par ailleurs cassé de partout, mais c’est une autre histoire), mais je pense que ça reste le cas (avec peut-être un an ou deux supplémentaires d’utilisation à plein temps du langage – on reste en dessous de 10 ans en commençant à zéro).

Eusèbe

Quand tu parles de « modèle mémoire », tu fais bien références à différents points au sujet de la représentation comme le fait que la taille d’un char soit de 1 byte, que la représentation des entiers signés est au choix en signe et magnitude, complément à un ou complément à deux, ou encore que les entiers ont peut-être éventuellement des fois des bits de bourrage ? Si oui, que reproches-tu plus précisément à ce modèle ? Je précise que cette question est de la pure curiosité, il n’y a aucune animosité derrière.

+0 -0

Loupé : https://www.tockos.org/documentation/getting-started . […]

Ah non pas "loupé", une grande partie des OS ont un noyau codé en C, donc tu m’excuseras, mais quand je voudrais étudier des cas concrêt je ne pense pas que je vais me pencher sur "Tock Embedded Operation Systems".

AlexandreDeMoura

Je disais "loupé" pour "je n’ai jamais vu aucun OS codé en Rust". Ben voilà si. Et pour étudier un cas concret, je dirai que les micro-noyau sont très clairement des cibles bien mieux choisies : ils sont de taille raisonnable ce qui les rend possible à prendre en main et à comprendre pour un humain.

D’ailleurs c’est typiquement le genre d’OS sur lequel on fait de la sécu actuellement pour deux raisons : ça se développe beaucoup à cause de tout ce qui est objets connectés et réseaux de capteurs, et le code est suffisamment petit pour qu’on puisse obtenir des garanties fortes dessus.

Et si tu aurais lu mes messages, j’apprend avec le livre de Tanenbaum et même si il fait une apparté sur le C++, la plupart des OS qu’il traite son codé en C.

AlexandreDeMoura

Et d’après toi, pourquoi sont ils codés en C ? Il y a une bonne part d’historique et de support. Rust a été développé récemment et n’est donc pas accessibles sur beaucoup de plateformes et n’a pas encore une base de code conséquente. Mais pour un développement from scratch aujourd’hui, c’est une option à envisager sérieusement.

Quand tu parles de « modèle mémoire », tu fais bien références à différents points au sujet de la représentation comme le fait que la taille d’un char soit de 1 byte, que la représentation des entiers signés est au choix en signe et magnitude, complément à un ou complément à deux, ou encore que les entiers ont peut-être éventuellement des fois des bits de bourrage ? Si oui, que reproches-tu plus précisément à ce modèle ? Je précise que cette question est de la pure curiosité, il n’y a aucune animosité derrière.

Taurre

C’est surtout la partie modèle mémoire dans le contexte concurrent ajouté par C11. Qui est connu pour être cassé sur deux points :

  • atomic_rlx autorise des trucs complètement farfelus au niveau UB et qui sont atrocement dur à détecter,
  • les optimisations communes des compilateurs selon ce modèle sont complètement unsound.

C’est surtout la partie modèle mémoire dans le contexte concurrent ajouté par C11. Qui est connu pour être cassé sur deux points :

  • atomic_rlx autorise des trucs complètement farfelus au niveau UB et qui sont atrocement dur à détecter,
  • les optimisations communes des compilateurs selon ce modèle sont complètement unsound.
Ksass`Peuk

Hmm… Ok, donc ce n’est pas le modèle en général qui est considéré comme mauvais, mais « seulement » la partie ajoutée par la norme C11 en rapport avec les threads.

À ce sujet, tant que la discussion est orientée sur les threads, petite question plus « existentielle » : est-ce véritablement au langage de fournir les outils pour gérer le multi-threading ? Je veux dire, techniquement, il faudra toujours passer par l’OS pour créer et gérer des threads. Dès lors, la gestion des opérations en découlant (comme les opérations atomiques), ne devrait-elle pas revenir également à l’OS qui fournirait alors une API pour ces dernières opérations ? Sur ce point, la bibliothèque pthread ne fait-elle pas le boulot qu’essaye de réaliser (en moins bien ?) la norme C11 ?

+0 -0

Hmm… Ok, donc ce n’est pas le modèle en général qui est considéré comme mauvais, mais « seulement » la partie ajoutée par la norme C11 en rapport avec les threads.

C’est effectivement ça qu’on appelle le "modèle mémoire". Si tu pensais à la façon dont les données sont représentées, on pourrait parler de "représentation mémoire" par exemple ?

À ce sujet, tant que la discussion est orientée sur les threads, petite question plus « existentielle » : est-ce véritablement au langage de fournir les outils pour gérer le multi-threading ? Je veux dire, techniquement, il faudra toujours passer par l’OS pour créer et gérer des threads. Dès lors, la gestion des opérations en découlant (comme les opérations atomiques), ne devrait-elle pas revenir également à l’OS qui fournirait alors une API pour ces dernières opérations ? Sur ce point, la bibliothèque pthread ne fait-elle pas le boulot qu’essaye de réaliser (en moins bien ?) la norme C11 ?

Il faut passer par l’OS pour faire plein de trucs, ce n’est pas vraiment la question ici. Le problème est de donner un sens (une "sémantique", au sens théorique du terme, qui a l’air un peu différent de ce pour quoi les C++iens utilisent ce mot) à des programmes concurrents, notamment en présence de data race (deux processus qui peuvent accéder "simultanément" à une variable 1).

Le modèle le plus fort est celui de la cohérence séquentielle : il stipule que les exécutions autorisées d’un programme correspondent aux entrelacements des instructions des différents threads. Le problème est que ce modèle n’autorise pas tout une classe d’optimisations des compilateurs. Par exemple, dans le programme suivant :

1
2
3
4
/* Initialement, x = 0 && y = 0. r1 et r2 sont des registres locaux à chaque processus */
/* Thread 1 */ | /* Thread 2 */
x = 1;         | y = 1;
r1 = y;        | r2 = x

Le compilateur (on peut aussi voir ça comme "le processeur qui exécute le thread 1, et n’est pas au courant de ce que font les autres") peut décider pour une raison d’inverser les deux instructions du thread 1, qui sont indépendantes : il s’agit d’une écriture d’une variable, et d’une lecture d’une autre variable. Cette optimisation est correcte dans le cas d’un programme séquentiel, mais ici elle change la sémantique du programme complet : elle permet d’arriver en fin d’exécution à r1 == 0 && r2 == 0, ce qui n’est pas permis par la cohérence séquentielle.

Une solution serait d’interdire les optimisations qui cassent ce modèle, mais c’est trop pénalisant pour les performances, donc on ne le fait pas. À une époque, le C se simplifiait la vie en disant simplement "en cas de data race, UB". Ici par exemple, tout était autorisé (puisque le thread 1 peut lire y "en même temps" que le thread 2 écrit dedans).

Depuis, il y a eu des progrès, et depuis C11 le C dispose d’un modèle mémoire un peu plus fin. Seulement il se trouve qu’il pose encore des problèmes, notamment parce qu’il autorise dans certains cas des optimisations qui cassent complètement la sémantique des programmes (des lectures out of thin air, c’est-à-dire qu’on peut lire dans une variable une valeur qui n’est présente à aucun endroit dans le code du programme).

On retrouve aussi le besoin de définir un modèle mémoire au niveau des processeurs eux-mêmes (historiquement, c’est d’ailleurs là que ça a commencé). Par exemple, dans x86 (qui est un des modèles les plus stricts, mais qui n’est pas non plus la cohérence séquentielle), le réordonnancement dont je parlais plus tôt est autorisé (et on peut donc avoir les deux registres à 0 à la fin de l’exécution du programme). POWER et ARM ont un modèle très relâché, et entre les deux il y a quelques architectures qui ont quelque chose d’intermédiaire (SPARC il me semble par exemple, mais je confonds peut-être).

Au niveau des langages, Java a aussi essayé de faire le même travail. Pour le coup je n’y connais pas grand chose, mais j’ai cru comprendre que c’était aussi bien cassé.


  1. Pour simplifier le problème, on peut commencer par le réduire aux accès "instantanés" (qu’on appelle souvent "atomiques", mais le modèle de C11 donne un autre sens à ce mot), c’est-à-dire en gros aux variables qu’on peut lire en une fois. Il faut comprendre ici que le problème "entre le moment où j’ai lu les 8 premiers bits de cet entier et les 8 derniers, il a changé" est orthogonal à ce qu’on cherche à résoudre. 

+0 -0

C’est effectivement ça qu’on appelle le "modèle mémoire". Si tu pensais à la façon dont les données sont représentées, on pourrait parler de "représentation mémoire" par exemple ?

Eusèbe

Dans mon esprit, le « modèle mémoire » faisait référence à la manière dont les données sont agencées en mémoire (ce qui inclut donc la représentation), mais aussi la manière dont elles peuvent être accédées et/ou modifiées (ce qui inclut par exemple la règle de strict aliasing ou la notion de « type effectif »). Maintenant, j’ai peut-être une définition un peu trop large.

Mais bref, ce n’est que de la terminologie, l’essentiel c’est que l’on se comprenne. ^^

Il faut passer par l’OS pour faire plein de trucs, ce n’est pas vraiment la question ici.

Eusèbe

Je me suis probablement mal exprimé. Ce que je veux dire, c’est : les problèmes d’accès concurrents doivent-ils vraiment être gérer par le langage lui-même ? Au lieu de disposer d’une syntaxe et de règles spécifiques, les accès concurrents seraient plutôt gérer via une bibliothèque externe et/ou système, à l’image de pthread qui permet de synchroniser des threads à l’aide de mutex afin d’éviter ces accès concurrents. Je me doute que cela sera sans doute pas aussi optimisé que si le compilateur traduit cela directement vers les instructions qui vont bien, mais est-ce que l’on y gagne pas en simplicité tant sur le plan du langage que du compilateur ?

+0 -0

Oui

Davidbrcz

Merci pour cet article, voilà qui répond à ma question. :)

… est-ce que j’ai vraiment répondu tout ce pavé pour que tu me reposes la même question juste en dessous ? :(

Eusèbe

Ben, disons que ton message ne répond pas vraiment à cette question… C’est en tous cas ce que j’en comprend à sa lecture. Si ce n’est pas le cas, tu m’en vois désolé.

Quoi qu’il en soit, j’ai eu la réponse à ma question. Un grand merci pour vos réponses. ;)

+1 -0

Je lâche ce lien. Je n’ai aucune idée de la qualité de la ressource mais on peut se dire que publié sur Research Gate ça doit être pas trop mal :)

Ricocotam

Research Gate n’a pas de peer review. « Publié sur Research Gate », ça veut dire « publié par quelqu’un ayant une adresse mail institutionnelle ». Dans ce cas-là, le type travaille bien dans ce domaine, mais en soi, rien ne m’empêche de publier un tel article sur ce site, alors que je ne suis pas du tout un expert du domaine.

+0 -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