Journal Nimrod, ça se rapproche du langage idéal

Posté par  .
Étiquettes : aucune
11
2
nov.
2009
J'ai fais la découverte d'un langage que je juge plutôt très intéressant. En effet, celui-ci se rapporche très fortement du langage de mes rêves! Son nom, Nimrod.

http://force7.de/nimrod/index.html


C'est un langage à typage statique, avec inférence locale.
Sa syntaxe est extrêmement proche de Python.

Néanmoins, le modèle objet diffère de Python. Par exemple Nimrod supporte les multimethodes. Les méthodes ne sont donc pas liées à une classe en particulier.

Pour moi le langage ressemble a un judicieux mélange de Python, Dylan et Lisp (pour les macro et les manipulation de l'AST)

Bref, tout cela me donne envie de l'essayer (là je ne peux pas, je suis au boulot ! )
  • # Langage idéal...

    Posté par  (site web personnel) . Évalué à 10.

    C'est très subjectif. Rien que pour la controverse sur l'utilisation de l'indentation dans le langage.

    Pour qu'un bon langage ait du succès, il faut aussi:
    - des bibliothèques facilement disponibles pour tous les usages (comme dans cPython ou Java par exemple)
    - un apprentissage doux pour les développeurs
    - ce qui permettrait d'avoir une base significative d'utilisateurs
    - un interpréteur/compilateur permettant des perfs décentes, pour avoir un maximum de domaines où le langage peut être utilisé
    - que plusieurs implémentations soient possibles sans trop de difficultés. Ce qui est difficilement compatibles avec une abondante bibliothèque (ex: "euh, wxNimrod n'est pas dispo pour l'implémentation Java").

    La question que je me pose donc: est-ce que langage apporte assez par rapport aux contraintes d'apprentissage?
    À mon humble avis, quand on crée un langage:
    - soit c'est pour un besoin particulier
    - soit c'est pour s'amuser (et là n'importe qui peut prendre un langage existant et son implémentation, l'améliorer un tout petit peu et dire "voila un nouveau langage qui est mieux que les autres") ou juste montrer que des avancées sont possibles
    - soit on a un plan à long terme, avec de vrais apports et de vrais besoins derrière
    • [^] # Re: Langage idéal...

      Posté par  . Évalué à 4.

      Pour les bibliothèques il y en a une bonne série :
      GTK2, the Windows API, the POSIX API, OpenGL, SDL, Cario, Python, Lua, TCL, X11, libzip, PRCE, ODBC, libcurl, mySQL and SQLite.

      Mais pas de Qt...

      Pour l'apprentissage, ça a pas l'air spécialement compliqué.

      Par contre, gros point noir (pour moi en tout cas): l'indentation comme partie intégrante du langage (comme tu l'as fait remarqué c'est sujet à controverse)

      par contre Gros point positif:
      * les variables ne sont pas implicites :)
      * Le switch/case à l'air plutôt sexy
      * les variables sont typées
      * des template :D

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

      • [^] # Re: Langage idéal...

        Posté par  (site web personnel) . Évalué à 3.

        >Par contre, gros point noir (pour moi en tout cas): l'indentation comme partie intégrante du langage (comme tu l'as fait remarqué c'est sujet à controverse)

        L'indentation ... Quand tu passe 80% de ton temps a lire du code ce genre d'obligation est tellement reposante. Soit tu est débutant et l'indentation ce sont les bonnes pratiques tout de suite. Soit tu n'est pas débutant et de toute façon, tu commente et tu indente.
        • [^] # Re: Langage idéal...

          Posté par  . Évalué à 2.

          Je me demande si les commentaires ne devrait pas également être obligatoires : mes scripts sont principalement en Python, et avec l'indentation, je me force à écrire un code propre, mais je ne prend jamais le temps de bien documenter (même si je sais que le script va pas mal servir).

          Alors ça serait peut-être intéressant d'avoir un langage qui force par exemple à commenter les classes et leur méthodes, les procédures, etc d'une manière standardisée (je crois qu'il y en a une en Python, il faudrait que je retrouver la PEP).

          Article Quarante-Deux : Toute personne dépassant un kilomètre de haut doit quitter le Tribunal. -- Le Roi de Cœur

        • [^] # Re: Langage idéal...

          Posté par  . Évalué à 9.

          >L'indentation ... Quand tu passe 80% de ton temps a lire du code ce genre d'obligation est tellement reposante.
          M-x indentAll
          une macro a moi :), ça indente tout le code.
          Par contre, j'ai déjà bossé sur du code python, et l'indentation par bloc, je regrette, mais c'est chiant. Quand tu dois indenter tout un bloc tenant sur 3-4 écrans (et je suis gentil), tu risque de rater la ligne qui sépare 2 blocs.

          Alors oui, le gars qui a écrit ce bloc monstrueux est un boulet, mais une mauvaise indentation avec des {} ça se résout avec une commande. Alors oui y a moyens de "replier" le code, indenter, déplier, faire un raccourcis emacs qui me le fait, mais ça reste lourd.

          Je ne parle pas des merges, quand tu as plusieurs personne qui on bossé sur la même zone.

          Enfin bref, j'ai testé les deux types, et je continu de dire que les blocs déterminé par {} ou if then end if, c'est mieux

          Et puis de nos jours les bons éditeurs font tous l'indentation à notre place, alors le code pas indenté ça n'existe que sur le web (autre problème de python quand le gars ne sais pas se servir des bonnes balises)

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

          • [^] # Re: Langage idéal...

            Posté par  (site web personnel) . Évalué à 3.

            > Quand tu dois indenter tout un bloc tenant sur 3-4 écrans

            Le problème c'est plutôt ton bloc de 3-4 écrans que l'indentation type python....
            Personnellement, un bloc qui fait 10 lignes je m'en méfie, qu'il y ai des {} ou non.
            • [^] # Re: Langage idéal...

              Posté par  . Évalué à 3.

              Mais là dessus on est complètement d'accord, mais le monsieur parle de passer 80% de son temps à lire du code, et si tu en es à faire ce type de job, tu tomberas tôt ou tard sur du code mal écrit, ou un machin qui teste les entrées d'un clavier, ou lit le premier mot d'une ligne d'un fichier, et appelant une fonction selon ce mot), et fatalement tu tomberas sur ce type de bloc.
              Sous emacs (comme vim) tu as des fonctions pour aller en début ou fin de bloc, sélectionner le bloc (encore faut il penser à s'en servir), mais pour d'autres personnes utilisant des machins "plus évolué" il manque quelques fonctionnalités de bases, et repasser après quelqu'un parce qu'il a raté une ligne en scrollant sur 3-4 écrans, c'est un peu lourd, surtout que le diff il montre qu'un immense bloc, au lieu de 2 accolades et un if.

              Personnellement, quand je code, mes fonctions tiennent en général sur un écran, sauf pour les entrées/sortie, ou les machins biens répétitifs, mais tout le monde n'a pas les même habitudes que moi.

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

              • [^] # Re: Langage idéal...

                Posté par  (site web personnel) . Évalué à 3.

                Je crois que vous êtes d'accord en fait, python est un excellent langage, mais il n'est pas vraiment adapté pour de gros projets en entreprise où les développeurs ne sont pas tous très compétents.
                • [^] # Re: Langage idéal...

                  Posté par  . Évalué à 10.

                  aucun langage n'est adapté quand les développeurs ne sont pas un minimum compétents...
                  • [^] # Re: Langage idéal...

                    Posté par  (site web personnel) . Évalué à 6.

                    Oui mais il y en a qui sont plus tolérants aux développeurs incompétents (ou avec des délais débilement courts). Avec des langages plus restrictifs, on tendra vers la catastrophe plus lentement.
            • [^] # Re: Langage idéal...

              Posté par  (site web personnel) . Évalué à 8.

              > Le problème c'est plutôt ton bloc de 3-4 écrans que l'indentation type python....
              > Personnellement, un bloc qui fait 10 lignes je m'en méfie, qu'il y ai des {} ou non.

              Pas forcément... Je me bat depuis longtemps contre les personnes qui considèrent ce genre de choses comme étant absolues, et qui veulent imposer des style de code sans réfléchir...

              J'ai deux exemples de code ou j'ai fait des fonctions de 150 à 200 lignes et qui sont bien plus lisible et ou le risque de bug est bien plus faible que leur équivalent découpé en petites fonctions.

              1/ L'implémentation de l'algo benson-pass-alive dans un jeu de go : Cet algo nécéssite 6 tableaux temporaires et tout un tas de petites variables qui sont utilisés tout aux long de l'algo.
              Il se découpe facilement en 5 ou 6 étapes: calcul des deux premiers tableaux, premier passage sur le goban, mise à jour des deux suivant, itération de l'algo...

              La version en une fonction déclare toutes les donnée au début de la fonction, les tableaux étant internes à l'algo se trouvent alloués dans la pile donc les perfs sont meilleures et il n'y a pas à se préoccuper de les désallouer, c'est fait automatiquement à la sortie de la fonction. Les variables gardent le même nom tout au long de l'algo.
              Chaque étape est bien séparée des suivantes par un court commentaire qui indique à quelle étape on en est, ce qui permet de se référer à la description de l'algo dans un gros commentaire avant le début de la fonction.
              Bref ça ce lit très bien et le code est facilement compréhensible.

              La version qui découpe les différentes étapes dans différentes fonction est par contre beaucoup moin lisible, chaque fonction prend une dizaine de paramètres l'algo en lui même se retrouve explosé, de manière logique bien sur mais c'est plus dur à suivre.
              Chaque fonction n'est appellée qu'une fois donc il n'y a pas de problème pour inliner le code mais ça reste moche.
              Le grand nombre de paramètre des fonctions fait qu'il est facile de ce tromper.
              Je vais pas détailler mais c'est beaucoup moins pratique et bien moins facile de comprendre ce qui ce passe vraiment.

              Bien sur ont peut aussi faire une structure ou un objet qui contienne toutes les variables et tableaux temporaire, mais dans ce cas la soit on a langage ou il faut gérer explicitement la mémoire et il faut faire une allocation qui coute cher et ne pas oublier le free. Si on a un langage ou la memoire est gérée automatiquement on ne sait plus vraiment ce qui ce passe ni quel est l'impact de l'allocation.

              2/ Le même genre de problème dans le calcul de l'espérance pour l'apprentissage d'un modele CRF. La aussi on a besoin de pas mal de tableaux intermédiaires qui sont chiant à faire passer d'une fonction à une autre alors que de simples variables locales sont tellement plus simple et regroupe toutes les étapes de l'algo au même endroit dans l'ordre ou elle sont éffectuées de manière logique et lisible.

              Donc même si de manière générale, il faut éviter les fonctions ou indentations longues, ce n'est pas une véritée absolue et parfois un code peut être écrit de manière bien plus sûre, lisible et maintenable et violant les style de code.

              Mon code pour l'éxemple deux est une fonction 175 lignes contenant notament une boucle for de 103 lignes. Une autre version du code qui est distribuée sur 5 fonctions fait au total 286 lignes.
              Pour avoir discuté avec 3 personne qui ont du utiliser les deux versions, toutes on admis que la première est bien plus compréhensible, et pour l'une d'elle ce fut vraiment très difficile à admettre...

              La seule chose avec ce genre de code c'est qu'il faut être très discipliné, avoir des noms pour toutes les variables qui soient parfaitement explicite et cohérent bien séparer toutes les étapes et avoir un gros pavé de commentaire avant la fonction expliquant ce qu'elle fait et comment elle le fait.
              Et bien sûr il ne faut utiliser ce genre de chose que lorsque c'est nécéssaire.
              • [^] # Re: Langage idéal...

                Posté par  . Évalué à 4.

                Bien sur ont peut aussi faire une structure ou un objet qui contienne toutes les variables et tableaux temporaire, mais dans ce cas la soit on a langage ou il faut gérer explicitement la mémoire et il faut faire une allocation qui coute cher et ne pas oublier le free. Si on a un langage ou la memoire est gérée automatiquement on ne sait plus vraiment ce qui ce passe ni quel est l'impact de l'allocation.

                T'es pas très juste dans ta comparaison, dans la plupart des langages encapsuler dans un conteneur ça change pas grand chose question allocation.

                En C par exemple, tu peux toujours l'allouer (la structure, l'objet) sur la pile et passer pointeur ou référence en paramètre aux procédures, ça ne change pas grand chose question allocation mémoire.

                En java, ça change rien non plus, tes tableaux sont alloués comme le reste il me semble, et à peu prêt tout est référence.

                Pleins de langages ont la notion de référence, dans les langages à gc t'as pas besoin d'oublier le free, dans les langages fonctionnels t'as pas d'effets de bords et les variables sont copiées au besoin si tu les modifies, elles ne sont pas réallouées si tu les modifies pas (copy on write) ...

                Bref, tu n'auras que les mauvais programmeurs qui vont faire des copies inutiles de leurs données ...
                • [^] # Re: Langage idéal...

                  Posté par  (site web personnel) . Évalué à 5.

                  as de bol d'avoir parlé du C vu que justement c'est le language que j'utilise dans les deux cas et qu'il est la source d'un argument supplémentaire dans le deuxième cas...

                  Pour l'algo sur les CRF je dois utiliser des tableaux à deux dimensions et plus dont la taille n'est pas connue à la compilation. Une des nouveautée cool du C99 est la tableau dynamiques qui me permmettent de faire :

                  int x = /* calcul de la taille X */;
                  int y = /* calcul de la taille Y */;
                  double tbl[x][y];

                  Le problème c'est que ce tableau ne peut pas se trouver dans une structure car la taille de la structure doit être connue à la compilation... De même, le passage de ce tableau en paramètre d'une fonction est embetant, soit je passe la taille des dimenssion en paramètre :
                  void mafonction(int x, int y, double tbl[x][y])
                  Ce qui devient vite les bordel si on a plusieurs tableau en paramètres. Soit ma fonction est capable de retrouver toute seule les dimension et donc je peut passer le tableau sous forme unidimentionelle, mais dans ce cas l'indicage devien chiant à mourir.

                  On est ici dans le cas ou une limitation du langage rajoute encore une couche au fait que le programme est bien plus lisible. La version splité en plusieurs fonctions se retrouve avoir des trucs du genre :
                  mdl->tbl[x * mdl->dimenx + y] = val;
                  ce qui est bien moins lible que juste
                  tbl[x][y] = val;

                  Mais si l'indicage est lié au langage, le fait de devoir aller chercher le tableaux dans une structure est lié à la décomposition. Pourquoi aller chercher un tableaux qui est juste une étape temporaire dans l'algo à l'interieur du structure qui donne l'impréssion d'avoir étée allouée quelque part ailleur ?

                  Bien sur, il est toujour possible d'avoir une structure "state" qui devient un fourtout pour toutes les variables à passer d'une fonction à l'autre. Mais dans ce cas pourquoi ce faire chier avec ce genre de truc :
                  void etape1(state *st) {...}
                  void etape2(state *st) {...}
                  void etape3(state *st) {...}
                  void etape4(state *st) {...}
                  void algo(void) {
                  state st;
                  etape1(&st);
                  etape2(&st);
                  etape3(&st);
                  etape4(&st);
                  }
                  alors que
                  void algo(void) {
                  /* etape1 */
                  ...
                  /* etape2 */
                  ...
                  /* etape3 */
                  ...
                  /* etape4 */
                  ...
                  }
                  est tout aussi clair, indique bien que les trois étape sont séquentielles, et n'oblige pas de faire une gymnastique avec une structure batarde ?

                  Et il ne faut pas oublier que ça simplifie le travail du compilateur. La sémantique et la portée des données et explicite et permet souvent des optimisations plus agréssive.

                  Perso, je pense toujours qu'il ne faut faire confiance ni aux dévelopeurs, ni au compilateur... donc je fais le code le plus simple, le plus lisible et le plus explicite possible, même si ça doit violer les style de codage.
                  Le compilo ne produira pas forcement du code plus rapide, mais dans tous les cas, il y a peut de chance qu'il soit plus lent.
                  Les autres dévellopeurs comprennent plus facilement mon code et on moins de chances de faire des conneries quand ils le modifient ou le maintiennent.
                  • [^] # Re: Langage idéal...

                    Posté par  . Évalué à 2.

                    Je suis assez d'accord avec l'ensemble de ton message, je parlais surtout de tes commentaires sur la gestion de la mémoire.

                    Effectivement, dans ce cas, on paie en C le fait que l'allocation sur la pile est super rigide,


                    Corrige moi si je me trompe cependant, mais le fait que les tailles soient dynamiquement calculée induit le fait que la taille du tableau est stockée quelque part sur la pile à côté du tableau, et que le compilo écrit lui même le calcul pour retrouver les adresses des adresses mémoires des cases du tableau ?

                    Du coup, on pourrait aller un peu plus loin en stockant dans la struct non plus le tableau en entier mais les adresses plus les tailles du tableau ... C'est une pure limitation du langage en fait, vu que du coup il est obligé de tout stocker en mémoire, exactement comme si on écrivait une classe ou une struct et les fonction qui vont avec pour gérer des structs ...

                    Ce qui me fait dire que dans le cas ou tu voudrais splitter ta fonction, tu aurais tout intérêt t à faire exactement ça et utiliser une structure de matrice, ou tu pourrais manipuler la mémoire de la pile si tu voulais ...

                    Bref, autant je suis d'accord avec ton argument "lisibilité" dans ce cas, autant l'argument "gestion de la mémoire" me convainc pas du tout :)
                    • [^] # Re: Langage idéal...

                      Posté par  (site web personnel) . Évalué à 2.

                      Tout d'abord quelques précisions sur la gestion des tableaux en C et surtout en C99. Le terme tableau dynamique est ambigüe dans le sens ou la taille des tableaux ne change pas. Elle est juste fixée à l'éxecution et non pas à la compilation.

                      Ce qui veut dire que si tu déclare : int tbl[3][5]; Le compilateur va produire du code pour allouer 15 emplacements sur la pile, et quand tu va indicer ton tableau, il va produire du code qui fait x * 5 + y. 5 est donc ici une constante qu'il peut stocker dans la pile, dans un registre ou dans l'instruction elle-même.
                      Quand tu fait : int tbl[X][Y]; Il va produire une allocation sur la pile qui commence par calculer la taille et ensuite réserve l'espace sur la pile. Pour l'indicage, c'est pareil sauf que cette fois ci la taille est forcement dans la pile ou dans un registre et ne peut pas être dans l'instruction elle-même.

                      Dans les deux cas, une fois la mémoire allouée sur la pile, il n'est plus possible de changer la taille du tableau; et ce n'est pas lié au C mais au principe même des allocation sur la pile.

                      Si l'on utilise la gestion interne des tableau par C99, on a un programme simple et lisible, aux prix de devoir tout mettre dans la même fonction.

                      Les solution alternative sont (ne pas oublier que l'on travail ici avec plusieurs tableaux) :
                      1/ continuer d'utiliser la gestion classique mais avec de multiple fonctions qui passe en plus des tableaux, leur dimension. On obtient des prototypes à rallonge et on augmente les risque d'erreurs au moment du passage de paramètres. Si l'on passe 4 tableaux à 2 dimension, ça fait 12 paramètres.

                      2/ on fait une grosse structure dans laquelle on passe le tout, ce qui nous donne :
                      typedef struct {
                      int *t1, x1, y1;
                      int *t2, x2, y2;
                      int *t3, x3, y3;
                      } state_t;
                      void etape1(state_t *st) {
                      ...
                      st->t1[x * st->y1 + y] = val;
                      ...
                      }
                      void algo(void) {
                      int x1 = ...;
                      ....
                      int t1[...], t2[...], t3[...];
                      state_t st = {t1, x1, x1, t2, x2, x2, t3, x3, x3};
                      etape1(&st);
                      ...
                      }
                      C'est un schéma très classique en C mais c'est tout sauf lisible. L'accès à un élément dans les sous-fonction est ien moins simple car le calcul que le compilo peut faire tout seul doit ici être fait de manière explicite.
                      La création et l'initialisation de la structure montre que l'on retrouve le même problème que lors du passage de paramètre: Une grosse liste de valeur à passer dans le bon ordre sans ce tromper.

                      3/ Faire une petite bibliothèque à côter pour gérer les tableaux. On note tout d'abord que même si elle est parfaite elle ne résout pas le problème. Dans le cas de l'algo de CRF, tu a 7 tableaux et 5 variables à passer aux différentes fonction, donc même si tes tableaux sont réduit à une structure, ça fait encore 13 variables donc tu est obligé de passer par une autre structure qui englobe le tout.
                      Ensuite, il devient difficile d'allouer cette structure dans la pile sans faire des acrobaties, imaginons la structure suivante :
                      typedef struct {
                      int *d, sx, sy;
                      } table_t;
                      Pour créer un tableau sur la pile il faut que tu ai quelquechose allouer sur la pile à mettre dans *d, ce qui te donne un code d'initialisation du genre :
                      int raw_d[x * y];
                      table_t tbl = {raw_d, x, y};
                      Ce qui n'est pas vraiment lisible, et tu as toujours le problème de l'indiçage.

                      Pour l'indiçage, une seule solution : une macro ce qui implique une syntaxe qui n'est plus celle des tableaux, donc moins lisible.
                      Pour la création des tables, tu ne peux pas utiliser directement une macro car la variable raw_d doit avoir un nom différent à chaque fois.
                      Donc la seule solution qui reste est de passer par une fonction qui fait un malloc et il ne faudra donc pas oublier de faire un free à la fin...

                      Comme tu peut le voir, c'est un truc que j'ai déjà pas mal potassé, et avant de faire des fonctions de cette taille je réfléchit toujours plusieurs fois et je cherche d'autre solutions.
                      Pour être honnête il y a une éventuelle solution au sujet de l'initialisation, tu peut faire une macro qui crée ta structure avec un "alloca" pour allouer les donnée sur la pile, mais ce n'est plus portable et ça ne résout pas le problème de l'indiçage qui est illisible.

                      Le problème ici n'est pas lié au langage mais au calcul que l'on souhaite faire. Ce calcul nécessite de construire de nombreux résultats intermédiaire qui sont utilisés tout au long des différentes étapes du calcul. Si l'on souhaite découper ce calcul en sous fonctions il est donc nécessaire de pouvoir faire passer un grand nombre de paramètre d'une fonction à l'autre sans que cela deviennent illisible.

                      Dans le cas du C ça demanderais deux modifications :
                      - pouvoir passer un tableaux dynamique à plusieurs dimensions dans une structure ;
                      - l'ajout d'une directive du style du "with" en pascal qui permet d'importer dans l'espace lexical local les nom d'une structure. ça permettrait de ce passer du "st->".

                      Cela ne résoudrais pas complètement le problème car il faudrait toujours construire et détruire cette structure, mais les sous-fonctions pourrait être lisibles.

                      L'aspect gestion de la mémoire était plus un élément anecdotique dans mon argumentaire au début, quand je listait les avantages que l'on a parfois faire de grosse fonctions ou gros blocs indentés.
                      • [^] # Re: Langage idéal...

                        Posté par  . Évalué à 2.

                        En fait non, ça nécessiterait juste de pouvoir passer une référence vers ton tableau dynamique dans ta structure, qui du coup pourrait être placé sur la pile sans soucis. Mais le langage ne permet pas de le faire sans acrobatie, c'est un peu un langage préhistorique, quand même. Quoi que ... si les références du C99 sont un peu malignes ...


                        Pour la structure, du coup, tu peux l'allouer sur la pile.


                        T'as aussi la solution bien crade, dans un langage objet, de mettre ton état dans les attributs d'un objet, ou dans d'autres langages de faire des fonctions imbriquées.

                        En fonctionnel des fonctions qui modifient ton état intermédiaire, dans une grosse structure éventuellement.

                        En Haskell peut être qu'une monade c'est ce qu'il te faut, mais je saurais pas dire.
                  • [^] # Re: Langage idéal...

                    Posté par  . Évalué à 2.

                    Pour info en C99 on peut écrire :

                    int mafct(int size)
                    {
                    struct
                    {
                    Header header;
                    unsigned char data[size];
                    Footer footer;
                    } maVariable;


                    }


                    Ça évite de faire les calculs d’offset soit même. Mais on ne peut pas déclarer la structure en dehors de la fonction.
                    J’ai utilisé ça, pour construire des trames ethernet. Je pense qu’il faut l’utilisé que quand ça améliore la lisibilité et que ça diminue grandement les risques de bug.
          • [^] # Re: Langage idéal...

            Posté par  (site web personnel) . Évalué à 0.

            <troll-inside>
            M-x indentAll... peut-être que ton éditeur n'est pas adapté à Python... ;-)
            </troll-inside>

            Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

  • # Oui

    Posté par  . Évalué à 8.

    Ça se rapproche du langage idéal
    Mmmh
    Sa syntaxe est extrêmement proche de Python.
    Ah oui, en effet.
    • [^] # Re: Oui

      Posté par  . Évalué à 6.

      Vivement vendredi.

      THIS IS JUST A PLACEHOLDER. YOU SHOULD NEVER SEE THIS STRING.

      • [^] # Re: Oui

        Posté par  (site web personnel) . Évalué à 1.

        vous êtes lourds, c'est lundi là... normalement, 'dredi c'est mercredi au plus tôt (en enlevant le d initial)
        • [^] # Re: Oui

          Posté par  . Évalué à 1.

          On n'est pas vendredi ?
  • # Mouais...

    Posté par  . Évalué à 9.

    Pour moi un langage idéal c'est un langage qui (en vrac) :
    - N'a pas de boucle (trop primitif)
    - Pas de variable (trop variable :F)
    - Pas de notion d'objet (trop restrictif)
    - Essaie de réduire au maximum les effets de bord
    - Permet de créer facilement des modules génériques et réutilisables
    - Statiquement typé via inférence de type
    - Compilable en code machine ou pour une machine virtuelle pour avoir des perfs décentes
    - Exécutable comme un script sans passé par une phase de compilation comme perl/python/ruby et cie
    - Possédant une plateforme de distribution d'applications et de libs

    ... ah mais il existe en fait mon langage idéal : http://haskell.org/

    ---> []
    • [^] # Re: Mouais...

      Posté par  . Évalué à 5.

      J'adore Haskell.
      Mais peut-être que je ne suis pas encore assez bon dans ce langage.

      Chaque fois que j'essaye de coder pour la vraie vie, je me retrouve avec des problèmes existentiels, qui font que le code n'avance pas.

      C'est pas une tentative de troll, juste mon ressenti actuel.
      Alors j'utilise Python pour la vraie vie, et Haskell quand je veux refléchir.
    • [^] # Re: Mouais...

      Posté par  . Évalué à 4.

      - Ne s'arrange pas pour compliquer les effets de bords au point qu'il faut avoir pas loin d'un doctorat en mathématiques pour comprendre comment faire des trucs triviaux (au hasard, comprendre les monades)

      Oups, ça exclut haskell.
      • [^] # Re: Mouais...

        Posté par  . Évalué à 2.

        Voici un guide pour comprendre les monades en douceur : http://www.haskell.org/all_about_monads/html/index.html

        Certes, Haskell est très différent des autres langages et certes il faut un certain investissement initial pour s'y plonger, mais je ne crois pas qu'il soit, au final, plus compliqué qu'un autre langage. Au contraire, le but final et de pouvoir exprimer beaucoup plus en écrivant moins.
    • [^] # Re: Mouais...

      Posté par  (site web personnel) . Évalué à 3.

      >> - Pas de variable (trop variable :F)

      main = let x = "etmonculcestdupoulet?" in putStrLn x

      >> - Pas de notion d'objet (trop restrictif)

      Objets et fermetures sont (grossièrement) isomorphes

      >> - Essaie de réduire au maximum les effets de bord

      Sur le papier.
      En pratique, c'est pareil que partout ; simplement les utilisateurs vont préférer tout passer en paramètre plutôt que de stocker dans une variable (et en pratique, une monade State, c'est des effets de bords, sinon c'est pas super efficace)

      >> - Permet de créer facilement des modules génériques et réutilisables

      Comme partout. Quand t'es prêt à passer trois fois plus de temps à généraliser ton code que t'en as passé à le créer pour résoudre ton problème.


      Bref, haskell (que j'adore), c'est pas la panacée, loin de là…
      En revanche, c'est hype, ça donne le poil luisant et ça attire les financements anglo-saxons.

      Encore une fois, le langage est un outil, et le langage X peut être super pour planter des clous, mais une bouse impossible pour tourner des vis.
      Quand j'ai besoin de Haskell, je sors mon ghc, mais quand j'ai besoin de perl ou de postscript, je vais pas me faire chier avec haskell.
      • [^] # Re: Mouais...

        Posté par  . Évalué à 2.

        Ma réponse précédente, un peu provocatrice, faisait référence aux langages traditionnels.

        * En Haskell, les variables se rapproche plus de constantes Java/C++ dans la mesure ou elle ne peuvent pas muter, un "a += 2" n'a aucun sens.

        * Le terme 'objet' est très large, là encore je faisais référence aux classes à la Java/C++ qui définisse un état interne et une série d'opérations liées à ces données. C'est surtout la notion d'identité qui s'oppose à celle de valeur.

        * Concernant les effets de bords, la garantit de transparence référentielle pour le fonctions pures est un avantage. Évidemment il est possible de dégénérer vers le passage systématique de tout l'état du système via une "state monade" ;)

        * Pour la généricité, elle est au coeur du système de type. Mais c'est vrai qu'il faudra toujours un effort supplémentaire pour généraliser du code.
  • # Très bon

    Posté par  . Évalué à 5.

    La syntaxe est simple et le langage a l'air puissant.

    Vivement un IDE et un debugger!
  • # Je n'adhère pas...

    Posté par  (site web personnel) . Évalué à 10.

    Case is insignificant in Nimrod and even underscores are ignored: This_is_an_identifier and this is the same identifier ThisIsAnIdentifier. This feature enables you to use other people's code without bothering about a naming convention that conflicts with yours. It also frees you from remembering the exact spelling of an identifier (was it parseURL or parseUrl or parse_URL?).

    je doute que les pythonistes apprécient.
    • [^] # Re: Je n'adhère pas...

      Posté par  (site web personnel) . Évalué à 8.

      Je ne fais pas de python, et déjà je n'apprécie pas....
    • [^] # Re: Je n'adhère pas...

      Posté par  . Évalué à 3.

      Effectivement, j'avais pas vu ça. Et c'est vrai que j'apprécie pas trop :(
      Dommage!
    • [^] # Re: Je n'adhère pas...

      Posté par  . Évalué à 0.

      glasses-mode \o/
    • [^] # Re: Je n'adhère pas...

      Posté par  . Évalué à 6.

      Un peu plus bas je trouve:
      Nimrod is also designed to allow teams accross the world to work together: identifiers are language insensitive. You can for example have a function named MyFunction and a french developper can use this function with MaFonction. Please note that you have to install the required dictionnary packages for this feature to work.
      • [^] # Re: Je n'adhère pas...

        Posté par  . Évalué à 7.

        Oui, je trouve que ça craint ce genre de chose, j'aime pas du tout.

        A mon avis c'est une fausse bonne idée, ça ne fait qu'ajouter de la complexité, pour un gain assez faible.
        Mais bon au moins là ça ne semble pas être le comportement par défaut.

        C'est vraiment dommage, car le langage semble vraiment bien conçu, et d'un autre côté on a ce genre de "feature", ainsi que le coup des underscore. J'ai un peu de mal a comprendre!
    • [^] # Re: Je n'adhère pas...

      Posté par  . Évalué à 3.

      je doute que les pythonistes apprécient.
      A vrai dire, même si cette solution est un peut extrême et apporte plus de problèmes que de solutions.
      Àhma de Pythoniste, Python traîne une tare depuis un moment, les multiples conventions de nomage de la bibliothèque standard. Entre:
      - les classes en camelcase ou lowercase: datetime, list
      - modules en camelcase ou lowercase: BaseHTTPServer, urllib
      - les methodes en camelcase, lowercase ou lowercase_with_underscore: date.fromordinal(), TestCase.setUp(), HTTPServer.close_request()

      Franchement à quand le respect de la PEP-8 ?
      Probablement jamais à cause du poids de la rétro-compatibilité. Une solution de ce genre, mais plus propre du genre alias, et avertissement de dépréciation m'aurait bien plut pour Python3. Mais bon faut voir l'ampleur du boulot aussi ...
      • [^] # Re: Je n'adhère pas...

        Posté par  (site web personnel) . Évalué à 4.

        Franchement à quand le respect de la PEP-8 ?

        ...Python 4, en 2020, avec 3to4 pour te signaler toutes les incompatibilités et modifs à faire :-)

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

        • [^] # Re: Je n'adhère pas...

          Posté par  . Évalué à 2.

          Mais est ce que les libraries auront commencé à migrer vers Python 3 d'ici là ?
      • [^] # Re: Je n'adhère pas...

        Posté par  . Évalué à 1.

        Si Python était insensible à la casse (comme Common Lisp par ex.) on aurait déjà moitié moins de problèmes.

        La conséquence directe c'est qu'en codant j'utilise parfois une mauvaise forme, et comme Python est dynamique il arrive que ça explose 3 mois plus tard quand une condition particulière est rencontrée.
        • [^] # Re: Je n'adhère pas...

          Posté par  (site web personnel) . Évalué à 6.

          donc en fait, ce que tu dis c'est que tu as mal codé, pas testé les cas particuliers mais c'est de la faute à python car il a fait exactement ce que tu lui as demandé de faire ?

          Mais en codant de la sorte (et si python est insensible à la case), t'es sur que tu vas pas non plus utiliser une variable maVariable alors qu'il y avait déjà mavariable plus haut, mais comme c'était dans une condition particulière ça explosera seulement 3 mois plus tard ?

          > Si Python était insensible à la casse on aurait déjà moitié moins de problèmes.
          franchement j'aimerais bien voir comment on aurait moitié moins de problèmes...
          en général l'avantage donné à l'insensibilité à la case est surtout de montrer que dans certains cas où on écrit de mauvais programmes n'importe comment ben finalement ça peut qd même marcher...

          de mon côté je préfère juste un poil plus de rigueur...
          • [^] # Re: Je n'adhère pas...

            Posté par  . Évalué à 4.

            C'est pas tant l'insensibilité des variables à la casse que l'abscence de déclaration des variables qui est en cause, en fait.

            C'est pas non plus forcément évident d'avoir des tests qui ont une couverture suffisamment importante pour couvrir tout les cas ...
    • [^] # Re: Je n'adhère pas...

      Posté par  . Évalué à 1.

      Il existe un mode Emacs qui fait ça, google-mode il me semble. Le camelCase est convertit en mots séparés par des underscores. J'utilisais ça quand j'en étais réduit à coder en VB6, ça a sauvé mes yeux.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.