Quelques nouvelles de Go, le langage de programmation

Posté par  (site web personnel) . Modéré par patrick_g.
37
5
déc.
2010
Golang
Le langage de programmation Go suit son chemin. Voici quelques faits marquants depuis la précédente dépêche sur LinuxFr.org :

Aller plus loin

  • # goland

    Posté par  . Évalué à 3.

    À une lettre près, on aura pu avoir un reportage sur ce language de Mickael Kael.
    • [^] # Re: goland

      Posté par  . Évalué à 1.

      Et à 2 lettres près on avait LEgoland ...
    • [^] # Re: goland

      Posté par  . Évalué à 0.

      Et si deux R font un G, la réécriture de linuxfr en RoR se fera en Go.
      • [^] # Re: goland

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

        Et si on change 5 lettres à coca ça fait chatte.
        • [^] # Re: goland

          Posté par  . Évalué à 6.

          Je suis sûr que ce n'est pas une coïncidence.
  • # Mais sinon, pourquoi je devrais m'intéresser à ce énième langage ?

    Posté par  . Évalué à 10.

    Bahh ! Je viens de lire rapidement la présentation de Rob Pike et le tout m'a laisser un drôle d'arrière goût :

    Pourquoi Go ?
    Pour obtenir un langage à la fois simple et performant. Arguments de poids pour toute personne ayant tenté d'utiliser du C++ ou de faire du calcul numérique sous Python.

    Structures, Méthodes et Interfaces
    Pour faire bref, l'équipe de Go a redécouvert le principe de simplicité des langages fonctionnels : définir des données simples et concentrer la complexité dans un ensemble de fonctions servant à modifier ces briques d'octets.

    Visibilité (public/privé)
    Aïe, différencier les membres publiques des privés par leur casse ! Ça pique aux yeux mais l'idée se tient. Après les goûts et les couleurs …

    Je m'étonne juste de l'argument "il est facile de repérer la présence ou non d'une majuscule, donc le code est plus simple à comprendre" après 3 diapos nous expliquant qu'en fait les interfaces on ne les déclare pas explicitement, si le développeur veut savoir quel type d'argument est accepté par ce bout de fonction, il n'a qu'à parcourir lui-même le code et vérifier que son objet implémente les-dites méthodes. Sur le coup, j'ai du mal à digérer l'argument de simplicité.

    Coroutines, fermetures, spaghettis stacks et autres joies de la programmation concurrente
    En fait Go n'est qu'une ré-écriture de Common Lisp maquillée avec une syntaxe à-la Algol, reprenant les concepts phares de CLOS, le tout agrémenté de pointeurs et muni d'une solide gestion des threads !

    … intéressant tout cela, intéressant … je m'en vais finir la lecture de Practical Common Lisp pour l'occasion ,-)
    • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

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

      Attention, il n'y a pas de coroutines en Go, mais des Goroutines. Ce sont une sorte de threads légers qui peuvent communiquer entre eux via des channels.

      Sinon, je n'ai pas fait de LISP depuis un bout de temps, mais il me semblait qu'il n'y avait rien dans Common Lisp pour gérer la programmation concurrente. Je me trompe ?
    • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

      Posté par  . Évalué à 3.

      Je suis d'accord, même si ce langage met ensemble des concepts intéressant, ça reste quand même un n-ème spinoff des langages qu'on connait.

      Ils ont éventuellement innové avec leur interfaces, mais perso je trouve ça super nul, ça aide pas du tout à bien structurer son code, et c'est super pas utile en terme d’interopérabilité pour quand on fait des libs et qu'on veut avoir des types qui sont compris de la même façon par tout le monde.
      La notion d'interface permet de donner une sémantique à ses méthode, et là, justement ce n'est que du structural typing statiquement typé !

      En fait, je vais comme à chaque fois revenir à ce que j'aime, mais je trouve qu'un langage comme Scala innove bien plus.
      Entre autres avec ses mixins, avec son typage VRAIMENT avancé (higher-kind et autres trucs du genre), avec une vraie réflexion sur le lien entre objets et fonctions.
      Et il a même du structural typing... !
      On est capable d'y retrouver tout ce qu'on connaissait du monde plus formel des langages fonctionnels, et de tout les délires venant de la théorie des catégories, ce qui permet de fabriquer des abstractions vérifiables (par exemple voir tout le travail sur la concurrence avec des librairies pour le pi-calculus, pour les acteurs, et le tout SANS primitives intégrées au langage contrairement à ce que déclare la présentation de Go comme étant obligatoire pour faire de la concurrence : c'est justement rendu possible par cet objet-fonctionnel).

      Enfin bon, Go c'est vachement bien, ça doit bien marcher, être optimisé, mais est-ce que ça va rendre le monde de la programmation et de l’ingénierie du logiciel meilleur ? Je ne pense pas !
      Scala ? Oui je le pense : avec de tels langages on développe de nouvelles manière d'aborder les problèmes (voir tout le travail sur les contraintes sémantiques encodées avec les types pour avoir plus de vérification et de sûreté à la compilation par exemple).
      • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

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

        Est-ce que Scala est utilisable en programmation système (ie. proche de la machine) ?
        (vraie question vs l'utilisation de la jvm derrière)

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

      • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

        Posté par  . Évalué à 1.

        > et c'est super pas utile en terme d’interopérabilité pour quand on fait des libs et qu'on veut avoir des types qui sont compris de la même façon par tout le monde.
        Je crois que tu n’as pas compris leur système d’interfaces. Une même interface est comprise pareille pour tout le monde. Si tu fais un minimum de Go, tu verras par exemple que l’interface Reader est utilisée absolument partout (dans io, http, json, logger,…), et tout le monde la comprend pareil. Idem pour l’interface Error.

        > La notion d'interface permet de donner une sémantique à ses méthode
        Ben oui, c’est ce que fait une interface en Go ; un ReadWriter, c’est un objet sur lequel on peut lire et écrire.
        Ou alors j’ai pas compris ce que tu voulais dire par « donner une sémantique à ses méthodes ».

        > et là, justement ce n'est que du structural typing statiquement typé !
        En quoi est-ce supposé être en contradiction ?

        > avec son typage VRAIMENT avancé (higher-kind et autres trucs du genre)
        Par exemple ?

        > avec une vraie réflexion sur le lien entre objets et fonctions
        Par exemple ?

        > (voir tout le travail sur les contraintes sémantiques encodées avec les types pour avoir plus de vérification et de sûreté à la compilation par exemple).
        Un lien ?
        • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

          Posté par  . Évalué à 6.


          Je crois que tu n’as pas compris leur système d’interfaces. Une même interface est comprise pareille pour tout le monde. Si tu fais un minimum de Go, tu verras par exemple que l’interface Reader est utilisée absolument partout (dans io, http, json, logger,…), et tout le monde la comprend pareil. Idem pour l’interface Error.

          Ben oui, c’est ce que fait une interface en Go ; un ReadWriter, c’est un objet sur lequel on peut lire et écrire.
          Ou alors j’ai pas compris ce que tu voulais dire par « donner une sémantique à ses méthodes ».


          Oui, je n'ai pas été très clair (et un truc m'échappe peut-être), mais en gros, comme ton interface est inférée implicitement, si tout le monde fait bien attention, alors ça va aller, mais imagine qu'une personne implémente un read et un write qui ne sont pas compatible (pour une raison qui m'échappe :) alors est-ce que cette chose implémente ReadWriter ou juste Reader et Writer ?

          Ce qui m'embête c'est cet implicite qui ne rend pas les choses explicites : quand je dis que j'implémente ReaderWriter, je signe un contrat pour une sémantique particulière, et peut-être qu'il y a plusieurs ReaderWriter, selon la sémantique.
          Quand j'implémente une méthode read, j'implémente une méthode read et je met la signification que je veux derrière.
          Sinon, avec des interfaces moins utilisées, des signification différentes vont émerger dans différentes parties du monde et un jour un mec va dire : ah zut, on a pas pareil, il faut se sync ! Ah oui mais merde, on est incapable de savoir à quelle sémantique ce rapporte cette implémentation ou celle-ci. Avec des interfaces, on a juste à regarder de quelle interface on parle (sans oublier qu'il y a un namespace qui permet de différencier les interfaces avec le même nom et ce, par le compilateur, pas un humain !).


          > et là, justement ce n'est que du structural typing statiquement typé !
          En quoi est-ce supposé être en contradiction ?

          Le fait que le lien méthode / interface est implicite avec le structural typing.
          Dans Go, l'interface ne sert que à donner des jolis noms à une définition structurelle d'un type, avec des interfaces à la Java, c'est plus qu'un nom, c'est un contrat à signer par ses implémenteurs.

          Et si tu manques de flexibilité et d'ouverture, il existe d'autres solutions qui s'inspire des type classes :
          http://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf

          Sur le typage avancé :
          Pour le concept : http://www.cs.kuleuven.be/~adriaan/files/genericshk/tcpoly-o(...)
          Pour son utilisation :
          http://drops.dagstuhl.de/opus/volltexte/2009/2338/
          http://www.comlab.ox.ac.uk//files/2187/ModularVisitor.pdf

          Pour la réflexion object / fonctionnel :
          http://infoscience.epfl.ch/getfile.py?docid=13847&name=T(...)

          Mais bon, ensuite il faut fouiller le web, il y a des millions de trucs passionnants :
          http://www.scala-lang.org/node/143
      • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

        Posté par  . Évalué à 5.

        même si ce langage met ensemble des concepts intéressant, ça reste quand même un n-ème spinoff des langages qu'on connait.
        Au départ je me suis dit la même chose : encore un langage qui ré-invente lisp. Mais Go comble une niche : un langage système type C avec plus de flexibilité (interfaces, fermetures, etc.) et un solide support des threads. Et dans ce domaine, j'ai vraiment du mal à lui trouver un concurrent.

        Ils ont éventuellement innové avec leur interfaces, mais perso je trouve ça super nul, ça aide pas du tout à bien structurer son code, et c'est super pas utile en terme d’interopérabilité …
        Petite nuance sur ce point : je préfère personnellement l'approche suivie par Go, qui est la même qu'en Common Lisp avec ses fonctions génériques ou en Haskell avec ses type-classes.

        L'idée est d'abordée l'écriture d'un programme de façon analogue à un théorème en mathématiques. Par exemple, "étant donné x réel et n un entier, on définit x à la puissance n par …" se traduit simplement en Go/CLisp/Haskell par "étant donné deux objets, le premier ayant une interface type Real et le second type Integer, alors on peut écrire notre fonction power ainsi ...".

        On se concentre sur les propriétés des objets, et non sur leur identité.

        C'est aussi plus facile d'étendre ces propriétés, il suffit juste d'écrire les méthodes requises par l'interface, plus la peine de perdre son temps à hériter, surcharger ceci et protéger cela.

        Non, le truc qui me chagrine, c'est le côté "implicite" des interfaces dans Go.

        Quant à Scala, c'est une autre histoire qui m'est malheureusement inconnue.
        • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

          Posté par  . Évalué à 0.

          si http://linuxfr.org/comments/1080981.html#1080981 est encore valable, c'est poubelle direct.
        • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

          Posté par  . Évalué à 3.

          Je te rejoins sur les typeclass de Haskell que tu peux effectivement ré-encoder aussi en Scala, voir le ma réponse au-dessus.

          Ce que je voulais mettre en avant c'est qu'il y a différentes utilisation des interfaces, et que Go n'en permet qu'une seule, qui bien que flexible, n'est pas la plus importante à mes yeux dans un monde on ton code a de grandes chance de se retrouver dans les mains d'un autre.

          Sinon, oui pour le langage de niche, mais c'est pour ça que je dis que c'est un n-ieme spinoff et qu'il n'innove pas.
          En revanche il répond à un besoin très clair, et je ne le nie pas !

          J'ai toujours tendance à m'exciter quand je commence à parler de Scala et parfois je peux paraître dédaigneux… Je m'en excuse !
        • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

          Posté par  . Évalué à 5.

          En Scala tu peux avoir des interfaces a la volée (comme sur la méthode inTheForest)

          class Duck {
          def quack = println("Quaaaaaack !")
          def feathers = println("The duck has white and gray feathers.")
          }

          class Person {
          def quack = println("The person imitates a duck.")
          def feathers = println("The person takes a feather from the ground and shows it.")
          }

          def inTheForest(duck: { def quack; def feathers }) = {
          duck.quack
          duck.feathers
          }

          Des interfaces implicites comme go :
          type Duck = { def quack; def feathers }

          def inTheForest(duck: Duck) = {
          duck.quack
          duck.feathers
          }

          Ou des traits explicites (equivalent du duo interface/classe abstraite de Java)
    • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

      Posté par  . Évalué à 5.

      >> En fait Go n'est qu'une ré-écriture de Common Lisp <<

      Ahem, tu oublie "juste" le typage statique..
      • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

        Posté par  . Évalué à 3.

        Ahem, tu oublie "juste" le typage statique..

        Arf oui, j'ai un peu forcé le trait :o

        D'ailleurs il existe bien d'autres différences entre ces deux langages. Mais les concepts ré-empruntés par Go font plaisir à voir (enfin des fermetures !).
      • [^] # Re: Mais sinon, pourquoi je devrais m'intéresser à ce énième langage

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

        Et alors, ça change quoi ?
        Ça veut dire que moins de programmes valides qu'on écrit en CL seront acceptés par Go, c'est tout !

        Puis coller un typeur à CL (ou un sous-ensemble) c'est pas dur…


        Tant qu'à faire, si je devais coder en Go, je programmerais sans doute en CL, pour compiler vers Go après au début, jusqu'à ce que les gens autour se rendent compte qu'il n'est en fait pas nécessaire d'utiliser Go…
  • # typage mou

    Posté par  . Évalué à 6.

    ce langage n'a pas de gestion strict du typage.

    Donc, longue vie aux bugs.

    Mais pourquoi réinventer la roue, elle s'appelle ADA, il faudrait juste

    lui rajouter des enjoliveurs.
    • [^] # Re: typage mou

      Posté par  . Évalué à 7.

      > ce langage n'a pas de gestion strict du typage.
      Qu’est-ce que tu entends par là ?
      C’est du typage statique, fort, à inférence locale. Je vois pas ce qu’il te faut de plus. C’est l’inférence locale qui te gène ? Pourquoi ?
    • [^] # Re: typage mou

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

      C'est marrant cette manie dans le monde du typage statique de toujours considérer son langage comme ayant un typage fort, et celui des autres un typage mou.

      Sinon, je tombe fréquemment sur l'argument "pas de typage fort => plein de bugs". Est-ce qu'il y a des études sérieuses qui montrent ce effet de cause à effet ?

      Je connais des études qui montrent que le nombre de bugs est très fortement lié au nombre de lignes de code et d'autres qui montrent que l'écriture de tests permettent de réduire fortement le nombre de bugs, mais je n'ai pas trop creusé la question du typage statique fort. Est-ce qu'un lecteur de linuxFr.org aurait un lien vers une ou plusieurs études à ce sujet ?
      • [^] # Re: typage mou

        Posté par  . Évalué à 6.

        Mmmh, si tu as un langage qui implémente réellement une forme forte de typage, alors en théorie, même si tu as un bug, celui-ci violera certainement les loi de ton typage et du coup ton programme plantera proprement. À comparer avec les langages à typage faible (par exemple le C), qui grogneront peut-être s'ils sont sympa à la compilation, sous forme de warning, mais qui malgré tout laisseront passer certaines conversions implicites. Du coup tu peux te retrouvé « coincé » à l'exécution, avec un programme qui va te donner des résultats faux, ou bien qui ne terminera jamais, etc.

        Le typage fort ne fait pas tout bien sûr, mais il assure presque à tous les coups que ton programme se terminera en cas de bug lié aux types. Je ne compte plus le nombre de fois où j'ai expliqué à des étudiants à quel point ils étaient chanceux d'avoir un bug reproductible en C (que j'adore par ailleurs)... :-)
        • [^] # Re: typage mou

          Posté par  . Évalué à 4.

          O'Caml serait l'avenir ?
          • [^] # Re: typage mou

            Posté par  . Évalué à 4.

            En fait c'est plutôt Haskell l'avenir.
            • [^] # Re: typage mou

              Posté par  . Évalué à 4.

              (vraie question, on est lundi, pas vendredi)
              C'est quoi la différence entre les deux, fondamentalement ?
              Merci,
              • [^] # Re: typage mou

                Posté par  . Évalué à 3.

                Alors je ne connais pas OCaml, mais dans les trucs qu'il n'a pas (enfin je crois) il y a l'évaluation paresseuse, les monades (mais on peut faire de
                l'impératif « naturellement » en OCaml) et je ne suis pas sûr qu'il ai les classes de types.
                • [^] # Re: typage mou

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

                  Pas d'évaluation paresseuse en OCaml ?
                  Ceci y ressemble pourtant:
                  http://caml.inria.fr/pub/docs/manual-ocaml/libref/Lazy.html
                  Certes, c'est dans la lib standard et pas dans le langage.

                  Pour les classes de types, je ne connais pas assez bien les aspects objet pour te répondre, je ne m'en sers que quand cela m'est vraiment utile. Ça m'est arrivé une fois, pour des raisons de compatibilité avec une API objet.
                • [^] # Re: typage mou

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

                  Dire qu'il y a des monades en Haskell, mais pas en OCaml, c'est un peu comme dire qu'il y a des design pattern en C++ mais pas en Java…

                  let concatMap f x = List.fold_left (@) [] (List.map f x);;
                  let return x = [x];;
                  let (>>=) v f = concatMap f v;;
                  let (>>) v f = let _ = concatMap f v in [];;

                  let test () =
                  [0;1;2;3;4;5] >>=
                  (fun x -> ["A";"B";"C";"D";"E"] >>=
                  (fun y -> return (x,y)));;


                  Et voila le travail.

                  Les monades, quand on code, c'est rien d'autre qu'une interface…
                  Et vu qu'OCaml a une couche objet, j'imagine qu'on peut même coder ça proprement, avec l'inférence de type qui se charge d'appeler les méthodes ">>=", ">>" et "return" correspondant à l'usage précis dans le code.
                  • [^] # Re: typage mou

                    Posté par  . Évalué à 3.

                    Oui donc j'avais bien fait de dire que je ne connaissais pas OCaml.
                  • [^] # Re: typage mou

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

                    J'ai déjà codé en OCaml, mais là...
                    let concatMap f x = List.fold_left (@) C'est quoi le @ ?

                    return n'est pas un mot clé ?

                    let (>>) v f = let _ = concatMap f v in [];;
                    pourquoi le let _ ? ça fait quoi

                    let test () = je comprend pas ce que ça signifie, syntaxiquement, sémantiquement...

                    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

                    • [^] # Re: typage mou

                      Posté par  . Évalué à 2.

                      ' _ ' c'est pas le nom pour dire « n'importe quel argument » ?
                    • [^] # Re: typage mou

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

                      @ c'est l'opérateur de concaténation de listes.
                      [1;2]@[3;4];; (* [1;2;3;4] *)

                      return n'est pas un mot clé. Dans la mesure où le langage est fonctionnel et où toute expression et tout statement retourne une valeur, ça serait inutile d'avoir ce mot clef [http://caml.inria.fr/pub/docs/manual-ocaml/manual044.html]
                      En haskell non plus ce n'est pas un mot clef.


                      let _ = foo
                      ça évalue foo puis ça jette le résultat. _ est un nom de variable valide, mais qui n'est accessible qu'en écriture. Tu peux donc faire let x = 3 in x mais pas let _ = 3 in _. C'est une info pour le compilo qui peut économiser des registres en ne sauvant pas la valeur retournée.
                      La raison est que (>>) ne garde pas son résultat, alors que concatMap va me rendre une liste. Idéalement, il faudrait que je code une autre fonction qui me retourne la liste vide, mais j'ai eu la flemme, et le code ci-dessus a la même sémantique. (Et si tu te demandes l'intérêt d'évaluer une expression pour jeter son résultat, rappelle toi qu'on peut faire des effets de bord, donc que let _ = foo () in 42 et 42 ne sont pas pareil.)


                      Pour ne pas comprendre
                      let test () = foo, tu n'as pas du faire beaucoup de d'Ocaml.
                      Ça déclare la *fonction* test qui n'a aucun argument. À chaque fois que tu l'appelles, foo est évalué.
                      let test = foo déclare la *variable* test. foo n'est évalué qu'une fois, lors de la déclaration de test dont la valeur —qui ne changera plus jamais— est le résultat de l'évaluation de foo.
                      • [^] # Re: typage mou

                        Posté par  . Évalué à 2.

                        >> return n'est pas un mot clé. Dans la mesure où le langage est fonctionnel et où toute expression et tout statement retourne une valeur, ça serait inutile d'avoir ce mot clef <<

                        Ca c'est très discutable, dans Eros il se sont rendu compte que dans certaines fonctions la valeur retournée n'aurait pas du l'être, ce qui peut être génant dans certains cas (capabilities).

                        Personellement je trouve que ce n'est pas une bonne idée d'avoir la derniere valeur d'une fonction retournée par defaut, je prefere que ce soit explicite.
                        Si tu considère 'return' comme étant trop lourd visuellement, alors '^' comme Smalltalk est un bon compromis..
                        • [^] # Re: typage mou

                          Posté par  . Évalué à 2.

                          Mais en fonctionnel pur, une fonction doit retourner quelque chose, sinon elle ne sert à rien. Pas d'effet de bord.
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 3.

                            1) Ocaml n'est pas un langage fonctionnel pur.

                            2) Si tu fais vraiment du fonctionnel pur, ton programme ne sert à rien puisqu'il n'a pas d'effet sur l'extérieur.

                            3) Tout les langages fonctionnels ont des moyens de faire des effets de bords..
                            • [^] # Re: typage mou

                              Posté par  . Évalué à 2.

                              > 1) Ocaml n'est pas un langage fonctionnel pur.

                              /o\ my bad, j'étais resté sur du Haskell.


                              > 2) Si tu fais vraiment du fonctionnel pur, ton programme ne sert à rien puisqu'il n'a pas d'effet sur l'extérieur.

                              Par forcément il peut retourner une valeur, puis tu interprètes cette valeur dans un autre programme écrit dans un autre langage.
                              (l'idée n'est pas de moi, j'ai lu un gars qui disait faire ça, un programme en haskell pour la partie « traitement » et un programme python pour le reste).
                            • [^] # Re: typage mou

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

                              1) Ce qui n'empêche pas que *tout* retourne une valeur en Caml, et c'est très bien. Libre au programmeur d'ignorer la valeur retournée.

                              2) Pas d'accord : il a un effet car tu peux mesurer son temps d'exécution s'il n'est pas paresseux. Et si ton programme est if (P = NP) then true else loop-for-ever() et que ton programme s'arrête, alors tu as un programme qui sert à prouver que P = NP.

                              3) Non. Sans doute la plupart de ceux qui ont un évaluateur ou un compilateur. Mais le lambda calcul original, celui sur papier, ne peut pas faire d'effets de bords, et est bien un langage fonctionnel. Qui plus est, on passe encore du temps à travailler dessus, j'imagine que ce n'est pas pour rien !
                        • [^] # Re: typage mou

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

                          >> Ca c'est très discutable, dans Eros il se sont rendu compte que dans certaines fonctions la valeur retournée n'aurait pas du l'être, ce qui peut être génant dans certains cas (capabilities).

                          Je viens de relire vite fait le papier sur Eros (ICFP'07), et je ne vois ni capabilités, ni retour de valeur qui n'aurait pu l'être autrement.
                          Je demande qu'on m'éclaire sur ce point.
                          Et tu peux *toujours* ne pas retourner de valeur, c'est à ça que servent unit ou les types sommes que sont Maybe a en Haskell et 'a option en OCaml.
                          Et encore une fois, décider « la dernière sous expression évaluée dans e est la valeur retournée par e » permet d'économiser un mot clef.


                          Je trouve un return inutile, point barre.
                          Le ^ de smalltalk est un échappement, une rupture du flot de contrôle —contrairement au cas où l'on retourne la valeur de la dernière expression évaluée— et tu peux très facilement le simuler si tu as envie ; il est donc inutile de l'imposer dans la mesure où la majorité des gens s'en passent gaiement.

                          (define (ma-fun x)
                            (call/cc (lambda (^)
                                       foo
                                       (if bar
                                         (^ h)
                                         quux)
                                       toto)))

                          Et une simple macro permet de rendre l'écriture du call/cc à la main inutile.
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 2.

                            Il a bossé sur trop de langages shapiro (Eros, BitC, ...), je n'ai pas réussi à retrouver ou il mettait cela.

                            Mais tu as raison qu'un type de retour vide permet d'éviter ça..
              • [^] # Re: typage mou

                Posté par  . Évalué à 3.

                Et je crois que la théorie derrière Haskell pour le typage est beaucoup plus puissante aussi.

                On est capable d'encoder plus d'information avec les types que avec ocaml (genre des contraintes et autre truc délires comme ça…)
              • [^] # Re: typage mou

                Posté par  . Évalué à 10.

                OCaml est un langage multi-paradigmes : tu disposes de constructions impératives (boucles, références) en plus de tes constructions fonctionnelles (les fonctions sont des valeurs manipulables comme les autres (1)). Ajoute à ça un typage statique fort qui possède de charmantes propriétés (comme la reconstructibilité : de toute expression tu peux déduire le type, tu n'es pas obligé de l'annoter - pas de déclarations chiantes comme en C ou autres). OCaml comporte également une couche objet qui pourrait être intéressante si les gens avaient l'habitude de l'utiliser (mais j'ai pas le sentiment que ça soit dans les mœurs).

                Haskell, lui, est « purement » fonctionnel : il ne dispose pas de constructions impératives. Il est également « paresseux » : les expressions ne sont calculées que quand c'est nécessaire. C'est le contraire des langages dits « stricts » (comme OCaml, mais aussi C, Java, Python… quasiment tout le monde en fait). Ça n'est pas à proprement parler une optimisation, parce que même si dans l'idéal ça évite de faire des calculs inutiles, en pratique ça demande davantage de tests, et ça peut rendre imprévisible le comportement du programme (notamment sa consommation mémoire). C'est une façon différente de programmer : ça t'autorise à flirter agréablement avec l'infini, en n'évaluant que ce qui est nécessaire.

                Haskell dispose également de ce qu'on appelle des « typeclasses » : ils permettent une surcharge intelligente des opérateurs et des fonctions sur plusieurs types. OCaml n'en dispose pas, et ne peut par exemple pas utiliser le même opérateur d'addition pour les entiers et les flottants : l'opérateur (+) a le type int -> int -> int et l'opérateur (+.) a le type float -> float -> float. Ça a l'air chiant, en pratique ça passe dans ce cas précis. Dans d'autres cas ça peut être un peu irritant. Haskell lui est plus évolué : l'unique opérateur (+) a pour type (Num a) => a -> a -> a . Le a est à lire comme un paramètre de type : ainsi, ce type veut dire « si A est une instance de la classe Num, alors si b et c sont des valeurs de type A, b + c est de type A ». Note bien que ce sont des *types* qui sont des instances de *classes*, pas des valeurs.

                D'autre part, certains problèmes sont naturellement impératifs : communiquer avec l'extérieur par exemple. Ceci se fait sans problème en séquençant des instructions Caml - par contre pour Haskell c'est plus difficile. Depuis un bon bout de temps maintenant, la seule façon conseillée de faire des entrées sorties dans ce langage est d'utiliser une construction élaborée appelée « monades ». C'est un mot qui fait peur aux débutants alors qu'il n'est pas très compliqué, mais ça ne s'explique pas en un paragraphe non plus. Les monades sont un concept provenant d'une branche très élaborée des mathématiques, appelée « théorie des catégories ». En gros, elles servent à séquencer des calculs - mais pas nécessairement de façon déterministe, c'est un concept plus général. Elles ne servent pas non plus uniquement à faire des entrées-sorties ou à simuler la programmation impérative. Et surtout, elles ne sont pas réservées à Haskell, il y a de nombreux langages modernes qui peuvent disposer de monades (OCaml ou C# par exemple).

                Voilà.

                (1) : au cas où tu ne connaîtrais vraiment pas les langages fonctionnels : si tu as déjà utilisé des langages impératifs, tu as certainement déjà manipulé des fonctions via des constructions comme les pointeurs de fonctions ou autres, et tu pourrais te dire donc que n'importe quel langage peut faire ça. En réalité, dans la famille des « fonctionnels » on regroupe les langages qui permettent de manipuler, et notamment de construire, des valeurs fonctionnelles. Par exemple, tu peux facilement définir un opérateur de composition de fonctions en Caml ou en Haskell. En C avec des pointeurs de fonctions, je ne vois pas vraiment comment faire.
                • [^] # Re: typage mou

                  Posté par  . Évalué à 4.

                  Merci à tous pour vos explications bien claires, je vois un peu mieux les différences maintenant.
                • [^] # Re: typage mou

                  Posté par  . Évalué à 5.

                  « [...] Ajoute à ça un typage statique fort qui possède de charmantes propriétés (comme la reconstructibilité : de toute expression tu peux déduire le type, tu n'es pas obligé de l'annoter - pas de déclarations chiantes comme en C ou autres). »

                  Mmmh, je trouve que c'est un peu déloyal de parler comme ça, à la limite de la malhonnêteté. [1] En OCaml, il y a bien inférence de type, mais dans le cas où tu mélanges différents types dans une fonction, et que tu n'as pas défini les interactions entre tous les types possibles que ta fonction accepte (le produit cartésien quoi), ben ce que renvoie ta fonction est un objet de type incomplet au mieux, qu'il faudra définir complètement par la suite. Quand tu n'as que quelques types à gérer tu t'en fous, mais dès que le nombre d'interactions entre types devient un peu complexe, ça commence à devenir pénible.

                  C'est pour ça que des langages type C, C++, Java, etc., déclarent les types des arguments etc. : pour « casser » la pénibilité en cas d'arguments multiples (entre autres choses hein). Et pourtant, si l'on excepte les types primitifs [2], Java utilise aussi la sûreté des types [3].

                  Mais quand on considère certains types de structures de données, genre (au pif) XML [4], ben là, chaque balise est un type, et dans un document XML classique, des types et des sous-types, y'en a ... fiou, tout plein. C'est là qu'interviennent des trucs (à ma connaissance pas implémentés dans les langages populaires, fonctionnels, ou impératifs) : le sous-typage sémantique. Y'a un langage preuve de concept qui a été créé pour l'occasion: CDuce. Il est dérivé des langages ML (d'ailleurs je crois bien qu'il nécessite OCaml pour être bootstrapé), mais sait correctement élaguer l'arbre des types/sous-types liés à un type donné. Fin bref, c'est très loin pour moi, tout ça, et mieux vaut aller voir de ce côté-là: http://cduce.org/

                  Tout ça pour dire que oui, OCaml est très bien, oui, il sait faire de l'inférence de type, mais clairement, non, ce n'est pas la panacée (par contre j'aime beaucoup son moteur de pattern matching pour le code, mais c'est une autre histoire).

                  [1] Je rigole hein ! :-)
                  [2] Oui, je sais, c'est un peu facile de dire ça ...
                  [3] Sur les objets donc... faire int toto = 3.2; va toujours fonctionner « à la C » et tronquer la valeur pour la stocker en tant qu'entier dans toto.
                  [4] XML qui inclut donc des types dans les types, ces types étant instanciés/présents (ou pas) en fonction des documents, etc.
                  • [^] # Re: typage mou

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

                    J'ai essayé de piger l'intérêt de Cduce, mais j'ai jamais réussi, c'est pas terriblement vulgarisé aussi...
                    Tu entend quoi par sous-type qu'il y en aurait plein ?

                    Pour moi du xml c'est tout simplement :

                    type xml =
                    | Element of (string * (string * string) list * xml list)
                    | PCData of string

                    Tes sous-types sémantique, ça serait prendre en compte le nom des balises et regarder la cohérence grammatical qu'il y a dans l'arbre ?

                    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

                    • [^] # Re: typage mou

                      Posté par  . Évalué à 5.

                      Ben oui, si y'a sous-typage sémantique, c'est qu'on va au-delà de la syntaxe. :)

                      Donc ta balise, ce n'est plus une simple chaîne de caractères, c'est un type à part entière (et je te parle même pas des schémas, qui permettent justement de typer « pour de bon » le contenu de tes balises et de t'affranchir du « tout est chaîne »). Je te renvoie lâchement ici : http://cduce.org/papers.html pour plus d'infos, mais je t'avoue que l'article initial (« semantic subtyping ») est franchement difficile à lire. Y'a une version plus sympa (« A gentle introduction to semantic subtyping »), qui fait l'impasse sur le moteur de pattern matching, mais qui reste difficile à lire.

                      Dans tous les cas, tu te retrouves avec un type qui contient d'autres types (c'est ce que montre l'article original: il prouve ce qui était pure conjecture par ailleurs : il y a une relation ensembliste entre un type et ses sous-types).

                      Au final, si tu as un arbre XML à traiter (par exemple pour trouver une certaine information), CDuce (et d'autres langages, genre XQuery, à supposer qu'ils bénéficient du même genre de fonctionnalités que CDuce dans leur implémentation) devrait être capable de rapidement élaguer l'arbre, pour rapidement trouver une réponse à la recherche faite dans le document.
            • [^] # Re: typage mou

              Posté par  . Évalué à 8.

              Haskell, c'est le nouveau Lisp: c'est l'avenir depuis très longtemps et cela le restera..

              Pour Haskell, une critique sérieuse est que l'évaluation paresseuse par défaut rend difficile l'évaluation des performances: des petites modifications peuvent induire des grandes variations de performances..

              L'autre critique sérieuse est que ce langage est difficile à apprendre.


              • [^] # Re: typage mou

                Posté par  . Évalué à 2.

                > Haskell, c'est le nouveau Lisp: c'est l'avenir depuis très longtemps et cela le restera..

                Il parait qu'Haskell perce un peu dans le domaine bancaire, pour la sécurité qu'il offre.

                > Pour Haskell, une critique sérieuse est que l'évaluation paresseuse par défaut rend difficile l'évaluation des performances: des petites modifications
                > peuvent induire des grandes variations de performances..

                Je ne vois pas trop quelle modification mineure pourrait induire les variations de performances dont tu parles.
                Parce qu'il faut un changement d'algo pour passer de l'un à l'autre. C'est un changement « d'approche ».


                > L'autre critique sérieuse est que ce langage est difficile à apprendre.

                Il y a quelques concepts un peu perturbant au départ c'est vrai, mais je trouve cela tellement amusant. C'est comme ré-apprendre à programmer/penser.
                • [^] # Re: typage mou

                  Posté par  . Évalué à 2.

                  > Je ne vois pas trop quelle modification mineure pourrait induire les variations de performances dont tu parles.

                  Je n'ai plus en tête le lien du papier, désolé.

                  Mais je connais un exemple proche: la récursion terminale très utilisée dans les langages fonctionnels: il est très facile de passer d'une récursion terminale a une récursion non terminale, ce qui change beaucoup les performances..

                  Et si le langage n'a pas de mot-clef pour différencier les appels de fonctions terminales des autres, le compilateur ne te préviendra même pas que tu viens de flinguer tes performances/ton nombre maximum de récursion..
                  • [^] # Re: typage mou

                    Posté par  . Évalué à 2.

                    Généralement en haskell une fonction non stricte appelée foo, sera appelée foo' dans sa version stricte.
                    Par exemple, foldl et foldl'.

                    Après pour le coup de la récursivité terminale ou non, bah c'est comme pour tous les langages je suppose, tu as des algos plus ou moins efficaces
                    mais tu ne vas pas indiquer pour chaque fonction -- dans son nom -- quelle stratégie tu utilises.
                    On va généralement l'indiquer dans la doc ou dans les commentaires.


                    > Et si le langage n'a pas de mot-clef pour différencier les appels de fonctions terminales des autres, le compilateur ne te préviendra même pas que tu
                    > viens de flinguer tes performances/ton nombre maximum de récursion..

                    Tu aurais un exemple de langage qui fait ça ?
                    • [^] # Re: typage mou

                      Posté par  . Évalué à 4.

                      Non, je n'en connais pas, mais ce serait une annotation intéréssante d'un point de vue maintenance d'un programme..
                      • [^] # Re: typage mou

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

                        En quoi ?
                        Savoir si un appel de fonction est en position terminale ou pas est décidable, et je n'ai pas souvenir de situation où un appel non terminal était préférable (ce qui ne veut pas dire qu'il n'y en a pas).

                        Et si j'écris
                        let rec fact n =
                          if n = 0 then 1
                          else n * ((fact (n-1))_terminal)

                        ce qui est absolument faux vu qu'il reste à multiplier par n après que l'appel récursif a retourné fact (n-1), il va se passer quoi ?
                        • [^] # Re: typage mou

                          Posté par  . Évalué à 3.

                          « Warning: non-terminal function marked as terminal »
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 3.

                            Exactement.

                            Pour répondre, à Axioplase note que je n'ai jamais dit qu'un appel de fonction non terminal pouvait être préférable à un appel de fonction terminal.
                            J'ai juste dit que s'il n'y a pas d'annotation, il est très facile dans une maintenance de modifier une fonction en rendant le dernier appel non terminal..
                            • [^] # Re: typage mou

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

                              J'aimerais qu'on m'explique les avantages possibles à choisir de rendre un appel non terminal.
                              Selon moi, plus qu'offrir des avantages (je n'en vois pas encore un seul), ça n'offre que des inconvénients : vu que tu stockes sur la pile tes adresses de retour, tu risques en mode débug de créer des erreurs inexistantes en mode « bon sens » via des débordement de pile. Et c'est encore pire quand tu as du parallélisme ou de l'évaluation paresseuse car tu peux ne plus savoir du tout qui a alloué quoi ni quand…

                              Le fait qu'on puisse le faire ne me justifie toujours pas qu'on veuille le faire ni que ce soit une bonne idée. L'optimisation des appels en position terminal date de la fin des années 70, et c'est sans doute pas pour rien que la norme du langage Scheme impose que tout appel de fonction en position terminale soit n'alloue pas de pile.


                              Vouloir remplacer les appels terminaux par des appels qui allouent sur la pile revient à vouloir remplacer une boucle while par des appels récursifs de fonction en C (qui allouent donc sur la pile). Si c'était une bonne idée, j'imagine que ça se saurait/ferait.
        • [^] # Re: typage mou

          Posté par  . Évalué à 6.

          Encore une fois : en quoi le système de type de Go n’est pas fort ? Ce programme ne compile pas parce que Go ne fait pas de conversion implicite entre float et int :

          func printFloat(f float) {
          print(f)
          }

          func main() {
          var x int = 5
          printFloat(x)
          }

          Il vous faut quoi de plus pour que ce soit du typage fort ?
          • [^] # Re: typage mou

            Posté par  . Évalué à 1.

            On veut des génériques d'ordre supérieur, des contraintes de types, des types classes.

            Voir par exemple :
            http://debasishg.blogspot.com/2010/08/using-generalized-type(...)

            Ou encore :
            http://debasishg.blogspot.com/2010/09/towards-generic-apis-f(...)
            • [^] # Re: typage mou

              Posté par  . Évalué à 6.

              Ça n’a rien à voir avec du typage « fort ».
              • [^] # Re: typage mou

                Posté par  . Évalué à 3.

                Oui, je sais, c'est plutôt du typage puissant :D

                Mais je pense que les gens ils veulent des trucs cools comme ça :)

                (et aussi je voulais encore me la ramener avec du Scala, désolé :>)
                • [^] # Re: typage mou

                  Posté par  . Évalué à 2.

                  Pas moi par exemple, je m’en fiche un peu. À part pour les collections, j’utilise jamais les génériques.
                  Et j’ai bien peur que ça finisse comme la métaprogrammation en C++ tout ça…
                  • [^] # Re: typage mou

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

                    Je m'intéresse un peu à Scala et c'est vraiment un langage assez génial.
                    Par contre au niveau de la syntaxe, je trouve que ça n'est pas super clair. J'ai l'impression qu'il y a un peu une tendance à abuser de la définition de nouveaux opérateurs.

                    Tiré de l'article cité ci-dessus :

                    # A =:= B, which mandates that A and B should exactly match
                    # A <:< B, which mandates that A must conform to B
                    # A A <%< B, which means that A must be viewable as B


                    Les opérateurs ne sont pas franchement explicites pour quelqu'un qui n'utilise pas ça tous les jours. Pourquoi ne pas utiliser des mots-clés genre "conform" "viewable" et "is" ou que sais-je ? Ca ne rendrait pas tout ça un peu plus clair ?

                    Qu'en pense ceux qui font du Scala régulièrement ? On s'y habitue facilement une fois qu'on est plongé dedans ?
                    • [^] # Re: typage mou

                      Posté par  . Évalué à 3.

                      Tu as raison, et on devrait aussi changer C/C++/Java/etc pour que "a < c" s'écrive "a lessThan c". Bon, c'est de la taquinerie, mais je trouve que justement, ce qui fait la force d'un langage (et qui le démarque des autres) c'est justement une partie de sa syntaxe et sa façon d'exprimer les choses. Ça passe aussi par des symboles bizarres, parfois. C'est aussi l'une des raisons pour lesquelles j'aime Perl, là où d'autres le détestent: tous ces marqueurs ($,@,%,...), ça les perturbe, alors qu'après pas mal de temps à les avoir manipulés, moi je trouve ça naturel.
                      • [^] # Re: typage mou

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

                        C'est aussi l'une des raisons pour lesquelles j'aime Perl, là où d'autres le détestent: tous ces marqueurs ($,@,%,...), ça les perturbe, alors qu'après pas mal de temps à les avoir manipulés, moi je trouve ça naturel.

                        Et comme tous professionnel dans sa branche, ça te permet de jargonner et de te sentir assuré par la particularité de tes connaissances ;-)

                        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

                        • [^] # Re: typage mou

                          Posté par  . Évalué à 2.

                          Gna gna gna, même pas vrai. :-) Le jargon, c'est le même que le tiens: « hash », « tableau », « scalaire ». :-)
                  • [^] # Re: typage mou

                    Posté par  . Évalué à 2.

                    Je me permet de vous partager une expérimentation personnelle sur quelques concepts de Haskell.

                    Quel programmeur n'a jamais eu la rébarbative tâche d'écrire une fonction de comparaison pour un objet/structure avec beaucoup de champs à comparer ? On se retrouve avec un arbre de if/else, ou autre structure de contrôle. Mes premiers pas en Haskell furent le théâtre d'abominables et naïfs

                    compare a b = case compare (field1 a) (field1 b) of
                        EQ -> case compare (field2 a) (field2 b) of
                            EQ -> case compare (field3 a) (field3 b) of
                                EQ -> compare (length (field4 a)) (length (field4 b))
                                ord -> ord
                            ord -> ord
                        ord -> ord


                    J'ai donc mis mon cerveau en branle pour profiter de la richesse de Haskell: généricité, type class, fonctions d'ordre supérieur, composition, applications partielles, inférence de type, etc.

                    En Haskell, on a la chance d'avoir le type Ordering, qui représente le résultat d'une comparaison par 3 constructeurs, plutôt que des entiers:
                    data Ordering = LT | EQ | GT
                    qui est une instance de Monoid, ce qui nous permet d'utiliser mappend, et mconcat en particulier, sa généralisation sur les liste:
                    class Monoid a where
                        mempty :: a
                        mappend :: a -> a -> a
                        mconcat :: [a] -> a

                    instance Monoid Ordering where
                        mempty = EQ
                        LT `mappend` _ = LT
                        EQ `mappend` y = y
                        GT `mappend` _ = GT


                    En outre, avec la fonction Data.Ord.comparing, on peut aisément comparer un champ, ou plus génériquement une propriété, des valeurs à comparer:
                    comparing :: Ord a => (b -> a) -> b -> b -> Ordering

                    Il nous est maintenant possible d'écrire facilement un enchaînement comparaison de propriétés, dont on retourne le résultat dès qu'on a divergence (LT ou GT):
                    compare a b = mconcat [comparing field1 a b, comparing field2 a b, comparing field3 a b, comparing (length . field4) a b]

                    Mais c'est encore très redondant et surtout généralisable! On aurait qu'à avoir la liste des champs/propriétés à comparer!

                    Cependant, comme une liste a un type donné, on ne peut pas voir une liste hétérogène.
                    C'est là qu'intervient les existential types! On va créer une fine enveloppe pour stocker nos propriétés à comparer, en garantissant le type d'entrée et la possibilité de comparer le type de sortie:

                    data Property a = forall p. Ord p => Prop (a -> p)

                    Il nous reste alors plus qu'à jouer du mconcat et du comparing pour écrire une fonction permettant de comparer séquentiellement sur une liste de propriété:

                    compareProps :: [Property a] -> a -> a -> Ordering
                    compareProps ps a b = mconcat $ map (\(Prop p) -> comparing p a b) ps


                    On peut maintenant réécrire notre comparaison plus simplement:
                    compare = compareProps [Prop field1, Prop field2, Prop field3, Prop (length . field4)]

                    Le code en question, avec les imports et tout, dans un exemple un peu plus concret: http://media.msieurhappy.net/pub/Properties.hs

                    Voilà, entre autre chose, ce que peut permettre un puissant système de type. :)


                    PS: J'ai essayé de faire au mieux, mais ma p'tite présentation est probablement très confuse et impénétrable si on a pas quelques notions de Haskell. Je m'en excuse par avance. /o\
                    • [^] # Re: typage mou

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

                      En Common Lisp, si tu veux comparer l'égalité entre deux structures :
                      > (defstruct toto x y z)
                      > (defparameter a (make-toto :x 10 :y 20 :z 10))
                      > (defparameter b (make-toto :x 10 :y 20 :z 10))
                      > (equalp a b) => T

                      Si on ne veux comparer que quelques champs, on peut écrire une petite macro qui va générer l'arbre if/else à notre place à la compilation. Et on pourra écrire un truc du genre :
                      > (fields-equal a b :x :z) => T
                      Bon je sors, j'ai un petit tutoriel à lire http://lisperati.com/haskell/ :-)
                      • [^] # Re: typage mou

                        Posté par  . Évalué à 2.

                        L'égalité (Eq) n'est pas la même chose que la relation d'ordre (Ord).
                        La majorité du temps, Haskell peut déduire tout seul l'opération d'équalité. Il suffit à la déclaration du datatype d'indiqué de dériver Eq

                        data Foo a b c = Foo { x :: a, y :: b, z :: c } deriving (Eq)

                        > Foo 10 20.0 "10" == Foo 10 20.0 "10"
                        True
                        • [^] # Re: typage mou

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

                          Ah, ok, merci pour la précision. Bon, alors la macro pour ne comparer que quelques champs ressemble à un truc comme ça :
                          (defmacro fields-equal (a b &rest fields)
                            `(and ,@(loop for f in fields
                                          collect `(equal (,f ,a) (,f ,b)))))

                          (defstruct toto a b c x y z)

                          (defparameter objet1 (make-toto :a 10 :b 20 :c "plop" :x 'plop :y 10.5 :z 10))
                          (defparameter objet2 (make-toto :a 10 :b 50 :c "plop" :x 'plop :y 10.5 :z 1001))

                          (fields-equal objet1 objet2 toto-a toto-c toto-y) => T
                          (fields-equal objet1 objet2 toto-a toto-c toto-y toto-z) => NIL

                          (macroexpand-1 '(fields-equal objet1 objet2 toto-a toto-c toto-y toto-z))
                          => (AND (EQUAL (TOTO-A OBJET1) (TOTO-A OBJET2))
                                  (EQUAL (TOTO-C OBJET1) (TOTO-C OBJET2))
                                  (EQUAL (TOTO-Y OBJET1) (TOTO-Y OBJET2))
                                  (EQUAL (TOTO-Z OBJET1) (TOTO-Z OBJET2)))

                          Évidement, on peut l'améliorer pour ne pas avoir à taper toto-*. On peut aussi imaginer faire la comparaison entre deux objets de structures différentes partageant des champs en commun (amis du type fort, bonjour :-) ).. Mais je ne suis pas sûr que ce soit vraiment judicieux.
                        • [^] # Re: typage mou

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

                          Bon, le code ci-dessous est crade, mais dériver EQ, c'est juste associer un nombre qui s'incrémente à chaque nouveau constructeur.
                          C'est d'ailleurs ainsi que c'est implanté en Caml, et sans doute en Haskell.

                          Et ça se fait en CL assez facilement.
                          (Après, il serait sans doute judicieux de passer par des méthodes génériques pour pouvoir traverser automatiquement des listes, vecteurs…)

                          (defmacro init-order-table ()
                          (defvar *order-table* (make-hash-table :test #'eql)))

                          (defmacro defconstant-ordered (&rest constants)
                          (cons 'progn
                          (loop for c in constants
                          for i from 0
                          collect
                          `(setf (gethash ',c *order-table*) ,i))))

                          (defmacro compare (sym1 sym2)
                          `(let ((v1 (gethash ',sym1 *order-table*))
                          (v2 (gethash ',sym2 *order-table*)))
                          (cond
                          ((= v1 v2) 'EQ)
                          ((< v1 v2) 'LT)
                          (t 'GT))))

                          (init-order-table)
                          (defconstant-ordered cFoo cBar)

                          (list
                          (compare cFoo cBar)
                          (compare cBar cFoo)
                          (compare cBar cBar))



                          type foo = Foo | Bar;;

                          [(compare Foo Bar);
                          (compare Bar Foo);
                          (compare Bar Bar)];;
                    • [^] # Re: typage mou

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

                      petit préambule : je n'ai jamais codé en haskell, ni dans un langage du genre (ocaml ou autre, à peine un petit peu d'emacs lisp)

                      ben franchement ça m'a l'air bien compliqué, ou plutôt ça donne l'impression de devoir se casser la tête pour pas grand chose finalement (juste comparer les champs de deux structures...)


                      var compare = function(a, b, props) {
                        var prop, i, l = props.length;
                        for(i = 0; i < l; i++) {
                          prop = props[i];
                          if(a[prop] !== b[prop]) {
                            return false;
                          }
                        }
                        return true;
                      };

                      compare(a, b, ["field1", "field2", "field3"]);


                      > Quel programmeur n'a jamais eu la rébarbative tâche d'écrire une fonction de comparaison pour un objet/structure avec beaucoup de champs à comparer ?
                      Du moment qu'on peut travailler avec introspection je ne vois pas vraiment le problème en fait...

                      ou alors j'ai pas capté le problème...
                      • [^] # Re: typage mou

                        Posté par  . Évalué à 2.


                        ben franchement ça m'a l'air bien compliqué, ou plutôt ça donne l'impression de devoir se casser la tête pour pas grand chose finalement (juste comparer les champs de deux structures...)


                        Ta solution ne répond pas au problème, on veut que "field1", "field2", "field3" soit des fields d'une structure de donnée qui soit typée, là tu manipule une espèce de map.

                        Ici le compilateur ne peut PAS vérifier que "field1", "field2", "field3" existe bien dans a et b quand tu fais appel à compare, donc tu dois TE faire confiance (ou à un des 25 mecs avec qui tu bosses :).

                        Sinon

                        Du moment qu'on peut travailler avec introspection je ne vois pas vraiment le problème en fait...

                        C'est pareil, tu dois te faire confiance pour ne pas faire de bêtises.

                        Alors sur un exemple comme ça, c'est pas la fin du monde (et encore avec ta solution, ça ne marche que sur les maps...), mais sur des plus gros trucs plus complexes ça fait mal à la tête de tout tester avec son cerveau :)
                        • [^] # Re: typage mou

                          Posté par  . Évalué à 2.

                          > là tu manipule une espèce de map.
                          Heu, non, en Javascript, x.foo et x["foo"] sont équivalents
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 2.

                            Et x["lol"] ça retourne quoi si x n'a pas été déclaré comme ayant membre lol ?
                            • [^] # Re: typage mou

                              Posté par  . Évalué à 2.

                              undefined, exactement comme x.lol :)
                              • [^] # Re: typage mou

                                Posté par  . Évalué à 1.

                                Oui donc bon, tu n'es pas dans du typage statique, d'où mon problème avec cette solution !

                                Ou alors ça te dit undefined à la compilation ?

                                Genre quand tu écris :
                                compare(a, b, ["field1", "field2", "field3"]);

                                Ça te dit : oulala attention, tu écris un truc pas très très possible là, parce que field3, ça va être undefined ?
                                • [^] # Re: typage mou

                                  Posté par  . Évalué à 1.

                                  > Oui donc bon, tu n'es pas dans du typage statique, d'où mon problème avec cette solution !
                                  En même temps, en JavaScript, ça risque d’être compliqué ;)
                        • [^] # Re: typage mou

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

                          > on veut que "field1", "field2", "field3" soit des fields d'une structure de donnée qui soit typée, là tu manipule une espèce de map.

                          J'avais bien compris, mais c'est écrit justement avec un langage me permettant de parcourir et d'utiliser les membres d'un objet en fonction de leur nom. C'est bien le but, non ?
                          Et oui, en quelque sorte tout est map en javascript... mais le problème n'est absolument pas là.

                          > Ici le compilateur
                          ha, j'avais pas compris que le but était de se reposer sur un compilo (perso j'aime pas me reposer dessus...)

                          > le compilateur ne peut PAS vérifier que "field1", "field2", "field3" existe bien dans a et b quand tu fais appel à compare
                          ok, pardon :

                          // a rajouter dans le for
                          if(!(prop in a && prop in b)) {
                            return false;
                          }

                          hop hop, je sais maintenant que mes champs sont dedans.

                          > et encore avec ta solution, ça ne marche que sur les maps...
                          et maintenant que tu sais que ça marche avec n'importe quel objet ?
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 1.

                            Super, et donc tu aimes jouer aux super-programmeurs, et faire des trucs qui peuvent être faits automatiquement. Wouhou...

                            Y'a suffisamment de cas où le compilateur ne fait pas bien son boulot pour lui laisser l'occasion de briller quand c'est plutôt chiant à faire à la main, tu ne trouves pas ?
                            • [^] # Re: typage mou

                              Posté par  . Évalué à 0.

                              > Y'a suffisamment de cas où le compilateur ne fait pas bien son boulot pour lui laisser l'occasion de briller quand c'est plutôt chiant à faire à la main, tu ne trouves pas ?
                              Qu’on soit clair : je n’ai jamais dit que ce genre de fonctionnalité n’était pas intéressante dans l’absolu. Simplement, je me pose la question du prix à payer pour de telles fonctionnalités. Si c’est pour se taper ensuite des pans entiers de code qui font de la « métaprogrammation » à la C++, merci mais non merci (vous avez déjà essayé de débugger un truc comme ça ? Un an après ? Écrit par quelqu’un d’autre ? Alors, oui, c’est type-safe et puissant, mais…). Si c’est pour avoir un langage qui nécessite une thèse en mathématiques pour comprendre pourquoi le compilateur râle sur ce bout de code alors qu’intuitivement il devrait pas, idem. Et je suis également assez sensible à la complexité du compilateur lui-même, du reste.
                              Je crois qu’on va là refaire le débat séculaire du « worse is better » : http://www.jwz.org/doc/worse-is-better.html :). Et étant clairement du côté worse-is-better, c’est la raison pour laquelle je me méfie de Scala et privilégie Go. Ce n’est pas un hasard si go a tant de succès auprès de suckless & co.
                              Enfin, je dis ça, mais apprendre Haskell est sur ma TODO-list depuis un moment ;) (plus pour ma culture que pour une réelle utilisation toutefois)
                              • [^] # Re: typage mou

                                Posté par  . Évalué à 5.

                                Mmmh, si le compilateur est capable d'inférer tout seul les types ou les champs qui devraient être initialisés sans que l'utilisateur ait quoi que ce soit à faire, je ne vois pas où est le problème (je ne parle pas d'un langage en particulier).

                                Le truc, c'est que ce qui te semble simple, voire évident, dans le code que tu as montré se transforme en code spaghetti à force de rajouter une condition par-ci ou une autre par-là. C'est ce que je voulais dire par « laisser le compilateur briller là où il le peut ». Un exemple tout bête: une multiplication de matrice.

                                Le code original (naïf et tout):

                                void matmul(const size_t m, const size_t n, const size_t k,
                                                    const double alpha, const double *a, const double *b,
                                                    const double beta, double *c)
                                {
                                    for (size_t i = 0; i < m; ++i)
                                       for (size_t j = 0; j < n; ++j)
                                            for (size_t l = 0; l < k; ++l)
                                                c[i*n+j] = beta * c[i*n+j] + alpha * a[i*k+l] * b[l*n+j];
                                }


                                Bon, tu peux t'embêter à faire tout un tas d'optimisations super intelligentes (et connues depuis 30 ans), du genre promotion scalaire, inversion de boucles, et tuilage, etc., ce qui pourrait donner un truc du genre :


                                void matmul(const size_t m, const size_t n, const size_t k,
                                                    const double alpha, const double *a, const double *b,
                                                   const double beta, double *c)
                                {
                                    for (size_t i = 0; i < m; ii += TILE_I)
                                        for (size_t l = 0; l < k; l += TILE_L)
                                            for (size_t j = 0; j < n; j += TILE_J)
                                                for (size_t ii = i; ii < MAX(i+TILE_I,m); ++ii)
                                                    for (size_t jj = j; jj < MAX(j+TILE_J,n); ++jj) {
                                                        acc = c[ii*n+jj] * beta;
                                                       for (size_t ll = l; l < MAX(l+TILE_L,k); ++ll) {
                                                            acc = c[ii*n+jj] + alpha * a[ii*k+ll] * b[ll*n+jj];
                                                        }
                                                        c[ii*n+jj] = acc;
                                                    }
                                }


                                Bon, je ne dis même pas que ce code est optimal (il est loin de l'être). Un bon exemple concernant ce genre de transformations se trouve ici : http://www.spinellis.g/blog/20090420/

                                Cependant, si je te dis que y'a toute une théorie qui existe déjà concernant les nids de boucle, et que ce genre d'optimisation peut-être faite par le compilateur sans que tu aies à lever le petit doigt, tu seras content non ? Ben le typage fort permet justement ce genre d'optimisations (enfin pas le tuilage, mais d'autres transformations/simplifications de code). Du coup quand je te vois faire ce que tu fais en JS (ou je ne sais quel autre langage), en rajoutant condition après condition et en disant « facile ! » en fonction de ce qu'on te dit que le compilateur sait déjà faire, je tique un peu. :)
                                • [^] # Re: typage mou

                                  Posté par  . Évalué à 2.

                                  > Un bon exemple concernant ce genre de transformations se trouve ici : http://www.spinellis.g/blog/20090420/
                                  Ton lien est mort

                                  > tu seras content non ?
                                  Oui, mais je fais la différence entre optimiser un truc simple qui marche et créer un truc complexe de manière innée et inhérente, c’est-à-dire qui est impossible à implémenter simplement.
                                  Ceux qui ont déjà eu des bugs en -O4 qui disparaissent en -O0 comprendront ce que je veut dire, pour les autres, je n’ai qu’une chose à dire : vous comprendrez tôt ou tard :)

                                  Il faudrait que quelqu’un écrive « The Fallacies of Programming languages » sur le modèle de « The Eight Fallacies of Distributed Computing », tiens. On y trouverait, entre autre :
                                  - le compilateur n’est pas buggué
                                  - la librairie standard n’est pas bugguée
                                  - les optimisations améliorent toujours les performances
                                  - les optimisations n’influent sur rien d’autre que les performances
                                  - un langage cohérent et élégant est facilement prévisible
                                  • [^] # Re: typage mou

                                    Posté par  . Évalué à 3.

                                    Oups, problème de copier-coller: http://www.spinellis.gr/blog/20090420/
                                  • [^] # Re: typage mou

                                    Posté par  . Évalué à 3.

                                    Alors, soyons bien d'accord: je sais à quel point un compilateur ça trompe énormément. Je sais entre autres parce que je bosse au même niveau (juste au-dessus du matériel, ou dans le compilateur).

                                    Cela étant dit: si tu prends n'importe quel guide sur l'optimisation de code (disons le manuel d'Intel sur la question par exemple http://www.intel.com/Assets/PDF/manual/248966.pdf, ou le site de A.Fog, http://www.agner.org), ou surtout des manuels plus haut-niveau (pour les gens qui ne veulent/peuvent pas passer le temps qu'il faut à micro-optimiser leur code), les méthodologies proposées impliquent souvent de compiler à différents niveaux d'optim (-O0,..., -O3), et de prendre un jeu d'essai représentatif -- bref, de faire à la main ce que certains compilateurs (icc, et normalement gcc aussi, par exemple) savent faire depuis un moment: de la compilation guidée par profilage.

                                    De plus, que -O3 puisse ralentir un programme, je le crois volontiers; qu'il donne des résultats faux (ou même que l'optimisation a eu un effet de bord surprenant, disons), à moins d'un bug dans le compilateur, c'est plutôt que l'utilisateur a fait des hypothèses quant au langage/à la machine qu'il utilise (je parle d'expérience).

                                    Concernant la cohérence et l'élégance d'un langage et sa prévisibilité, je ne suis pas certain de comprendre ce que tu veux dire par là. La plupart du temps (mais clairement pas toujours), plus de concision implique plus de clarté, mais cela suppose néanmoins une compréhension du langage, et de comment il fonctionne. J'ai l'impression qu'une bonne partie des reproches faits aux langages « différents » (qu'ils soient fonctionnels, tels que ML, Haskell, LISP, déclaratifs tels PROLOG, ou bien juste « glu » genre Perl) est qu'ils ne fonctionnent pas comme leurs cousins impératifs tirés du C. J'ai exactement le même problème avec Fortran par exemple, et pourtant il n'est pas si éloigné du C que ça (en supposant qu'on passe à Fortran 90 au minimum pour avoir la forme libre de syntaxe).
                      • [^] # Re: typage mou

                        Posté par  . Évalué à 1.

                        La différence majeure étant la garantie à la compilation que les champs comparés existent.
                        Et bien plus encore, car le Property enveloppant une fonction, on peut effectuer des traitements sur les champs avant de les comparer, encore une fois, avec la garantie sur les types.

                        Si je vais à l'essentiel du fonctionnement de la méthode expliquée, j'ai besoin que de 2 lignes:

                        data Property a = forall p. Ord p => Prop (a -> p)

                        compareProps ps a b = mconcat $ map (\(Prop p) -> comparing p a b) p


                        Pour illustrer les traitements possible, field2 est une liste d'entier dont on comparera la somme plutôt que les éléments, field3 est une chaîne de caractères qu'on comparera en négligeant la case:

                        compareProps [Prop field1, Prop (sum . field2), Prop (map toLower . field3)] a b
                        • [^] # Re: typage mou

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


                          var compare = function(a, b, props) {
                            var prop, field, comp, i, l = props.length;
                            for(i = 0; i < l; i++) {
                              prop = props[i];
                              field = prop.field;
                              if(!(field in a && field in b)) {
                                return false;
                              }
                              if("comp" in prop) {
                                comp = prop.comp;
                                if(!(comp in a[field] && comp in b[field]) {
                                  return false;
                                }
                                if(a[field][comp]() !== b[field][comp]()) {
                                  return false;
                                }
                              } else if(a[field] !== b[field]) {
                                return false;
                              }
                            }
                            return true;
                          };
                          compare(a, b, [{field: "field1"}, {field: "field2", comp: "sum"}, {field: "field3", comp: "toLowerCase"}]);


                          Bon, évidemment sum, toLowerCase doivent exister. Le code devient plus gros, mais c'est juste que le map n'existe pas de la même manière, mais au final je suis toujours totalement dynamique et ma comparaison de champ reste facile et simple à écrire.

                          Non pas que je veuille que haskell ne serve à rien, mais j'ai toujours pas compris l'intérêt à se casser la tête. Peut-être par rapport à des langages pauvres (comme c/c++/java par exemple) mais par rapport à js, as3, surement ruby, peut-être python ça me parait bien complexe (faut vraiment réfléchir pour comprendre le code haskell un peu plus haut, d'ailleurs le cheminement n'est pas simple, alors que c'est bidon, juste comparer une liste de propriété)
                          Maintenant, je pense bien que ce genre de paradigme à une utilité, enfin j'espère ;-)
                          • [^] # Re: typage mou

                            Posté par  . Évalué à 1.

                            Il y a un malentendu à dissiper: le but n'est pas d'établir une relation d'égalité, mais une relation d'ordre (plus petit, égal, plus grand → LT | EQ | GT) sur une liste de membres, éventuellement en leur appliquant des transformations, tout en garantissant le fonctionnement du code à la compilation.

                            Mon code tient en 2 lignes (hors imports et la signature de la fonction, cette dernière étant uniquement pour aider à la compréhension du code, pour peu que le système de type de Haskell ne soit pas du chinois pour soi. ;)) ce qui me semble assez élégant et succinct.

                            En outre, le propos n'était pas tant de débattre sur l'utilité pratique de mon bout de code que de montrer les possibilités d'un système de type fort, statique et puissant. J'en convient, ça n'a probablement aucun intérêt quand on fait du JS, mais là n'est pas le propos. ;)

                            ha, j'avais pas compris que le but était de se reposer sur un compilo (perso j'aime pas me reposer dessus...)
                            L'exploitation du compilateur permet 1/ d'éviter des erreurs de programmations qu'on découvre qu'à l'exécution 2/ d'éviter un surcoût à l'exécution pour valider les données.
                            • [^] # Re: typage mou

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

                              > mais une relation d'ordre
                              ok, j'avais zapé ce point...

                              > en 2 lignes (hors imports et la signature de la fonction
                              Si je met ma méthode dans un import, mon code tiens en une ligne (hors import et signature de la fonction)...

                              > En outre, le propos n'était pas tant de débattre sur l'utilité pratique de mon bout de code que de montrer les possibilités d'un système de type fort, statique et puissant.
                              ha mais je suis totalement d'accord. C'est juste que, ne connaissant pas les langages de ce type, à la lecture du cheminement pour écrire ton morceau de code, j'ai eu l'impression que c'était compliqué pour faire trois fois rien. Et j'ai l'impression que cette complexité vient directement du type de langage d'où le fait de montrer qu'on peut faire plus "simple" (au niveau du raisonnement, de la logique du code) pour arriver à une fonctionnalité assez équivalente.
                              Maintenant, il y a surement plein de cas où ce serait le contraire je pense... (ok, peut-être qu'il faudra un jour que je prenne le temps de regarder ce genre de paradigme...)

                              > L'exploitation du compilateur permet 1/ d'éviter des erreurs de programmations qu'on découvre qu'à l'exécution
                              oui, mais mon avis est que lorsqu'on se repose trop souvent sur un compilateur, on oublie de réaliser les tests soit-même. Et on se retrouve avec une tripoté de "codeurs" qui font : 2 lignes de code, CTRL-S, je regarde la sortie du compilo, je corrige si nécessaire, sinon je passe à la suite.
                              Le problème est que ces personnes, en se reposant exagérément sur le compilo ne savent finalement plus coder correctement mais seulement réagir face à une erreur à la compile. Et résultat, de part cette faillibilité on se retrouve avec plein de trucs zarb à l'exécution car c'est mal réfléchi et que le compilo ne peut pas tout faire.
                              • [^] # Re: typage mou

                                Posté par  . Évalué à 4.

                                Je pense effectivement que j'ai assez mal présenter les choses. Et qu'il fallait être dans ma tête pour avoir une vision claire de mon cheminement mental.

                                L'idée était de montrer l'utilisation de multiples facettes du système de type et que ça pleine compréhension permet d'écrire du code sûr et néanmoins court.

                                j'ai l'impression que cette complexité vient directement du type de langage d'où le fait de montrer qu'on peut faire plus "simple" (au niveau du raisonnement, de la logique du code) pour arriver à une fonctionnalité assez équivalente

                                C'est la nature de l'approche qui est très différente. Et c'est bien là qu'on constate la différence de paradigme: fonctionnel vs impératif (à objets). L'apparente complexité provient à mon avis qu'en Haskell on manipule des concepts plus élaborés et plus abstraits, mais le code s'en trouve simplifiée: composition + fonction d'ordre supérieur. Alors qu'en JavaScript on manipule des concepts plus basics (et plus familiers), mais on se retrouve avec un code plus complexe, avec de multiples branchements conditionnels, et plus sujet aux erreurs de programmation. En outre, le code JS n'est même pas équivalent.

                                Si j'en fais un module complet:
                                {-# LANGUAGE ExistentialQuantification #-}
                                module Properties where

                                import Data.Monoid (mconcat)
                                import Data.Ord (comparing)

                                data Property a = forall p. Ord p => Prop (a -> p)

                                compareProps :: [Property a] -> a -> a -> Ordering
                                compareProps ps a b = mconcat $ map (\(Prop p) -> comparing p a b) ps

                                (les imports sont de la lib standard)

                                Si quelqu'un a l'équivalent dans un autre langage de programmation, ou mieux, qu'il n'hésite pas. :)

                                mais mon avis est que lorsqu'on se repose trop souvent sur un compilateur, on oublie de réaliser les tests soit-même

                                C'est clair que c'est pas parce que ça compile que ça fonctionne correctement. Ça ne remplace pas l'écriture de tests. Mais la cohérence forcée du typage par le langage (parce que ça marche aussi bien avec un interpréteur qu'un compilateur en Haskell) permet de formaliser une partie du code et d'offrir des garanties que tu ne peux pas offrir en JS. Alors c'est sûr que pour un script JS sur une page Web l'intérêt est limité, mais dans plein d'autres applications, on va apprécier cette fonctionnalité.
                                • [^] # Re: typage mou

                                  Posté par  . Évalué à 4.


                                  Mais la cohérence forcée du typage par le langage (parce que ça marche aussi bien avec un interpréteur qu'un compilateur en Haskell) permet de formaliser une partie du code et d'offrir des garanties que tu ne peux pas offrir en JS. Alors c'est sûr que pour un script JS sur une page Web l'intérêt est limité, mais dans plein d'autres applications, on va apprécier cette fonctionnalité.


                                  Je rebondirais même là dessus pour ajouter que ça peut parfois remplacer les tests.

                                  L'exemple le plus connu et qui fait vraiment mal au cul quand on se remet au Java après avoir fais du Scala, c'est tout ces tests à écrire juste pour s'assurer qu'il n'y a pas un null qui traine.
                                  La contrainte : "{ce paramètre,valeur de retour,etc…} ne peut pas être null" peut être exprimée avec des types !

                                  Et bin on peut faire pareil avec pleins d'autres contraintes encore plus sympa :)

                                  (Et là je ne parle que de type, contrairement à msieur happy qui nous parlait de prog fonctionnelle ET de types :)
                                  • [^] # Re: typage mou

                                    Posté par  . Évalué à 2.

                                    Oui enfin là je ne te suis pas du tout hein. Java a un typage fort pour les objets. Le système de types en interne suit les règles de l'art en ce qui concerne le typage (cf le bouquin de Benjamin Pierce).

                                    Et qu'il n'existe pas d'outils en Java pour correctement vérifier qu'une variable est non-null est une chose. Typiquement lors de l'écriture d'une méthode, un IDE comme Eclipse signalera toute variable susceptible d'être non-initialisée, à l'exception des variables passées en paramètre. Après, qu'il faille un outil pour vérifier que l'articulation des méthodes (le graphe d'appel des fonctions quoi) passe bien des arguments non-null (en supposant que ce ne soit pas autorisé), c'est un autre problème... Cela dit je n'ai pas fait de Java depuis longtemps, et je me demande si les ajouts syntaxiques au langage (annotations, etc) ne permettent pas de détecter ce genre de trucs ...
                                    • [^] # Re: typage mou

                                      Posté par  . Évalué à 3.

                                      En fait il existe des outils qui font ça, voir par exemple findbugs dont on a parlé sur linuxfr il n'y a pas si longtemps.

                                      Mais on ne peut pas encoder cette contrainte au niveau des types (en fait on pourrait dire que findbug étant le typage pour encoder ce genre de chose, c'est juste que c'est un typage pas compris par le compilateur Java mais compris par le vérifieur findbugs).

                                      Donc Java a un typage fort, mais il est pas suffisamment fort, contrairement à Georges.
                                      • [^] # Re: typage mou

                                        Posté par  . Évalué à 4.

                                        Pourtant Java a la classe aussi ! :-/
      • [^] # Re: typage mou

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

        > Sinon, je tombe fréquemment sur l'argument "pas de typage fort => plein de bugs". Est-ce qu'il y a des études sérieuses qui montrent ce effet de cause à effet ?

        Personne n'a de liens à ce sujet ? Ce serait juste une légende urbaine ?
        • [^] # Re: typage mou

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

          Il y a quelques années, le Fortran s'est doté de l'instruction 'implicit none" . Je l'ai aussitôt utilisée et imposée à mes techniciens. Ils ont un peu râlé les premiers jours mais ont très vite compris l'intérêt d'un typage strict et non implicite car les erreurs dues à un typage laxiste sont parmi les plus difficiles à détecter.
        • [^] # Re: typage mou

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

          Google donne pas grand chose : http://scholar.google.fr/scholar?hl=fr&q=strong+type+%2B(...)

          J'ai l'impression qu'il y a pas vraiment d'étude sur le sujet. Après mon expérience perso me fait penser que "typage fort => Moins de bugs".

          J'ai pratiqué, dans l'ordre le :
          - Basic (quand j'étais gamin, ya 20 ans donc)
          - Pascal (pas mal)
          - C
          - Ocaml
          - (SQL)
          - Lisaac
          - Java
          - Ruby

          Typiquement, en caml, quand le compilateur me dit "ok" en général ça marche. Mais c'est pas très représentatif, parce que je l'utilise surtout dans des problématique ou je dois manipuler des grammaires.

          Pour les langages objets, entre java, lisaac et ruby, ce qui est indéniable dans mon expérience, c'est les Call On Null.

          En java et ruby, je m'en prend plein partout à l'exécution. D'où une boucle, trouver où c'est, corriger, relancer/retester.
          En Lisaac, pas mal de Call on Null sont détectés à la compilation, et c'est un vrai gain (surtout depuis l'ajout param w_null du compilateur dont la stable est en préparation, qui nous affiche tous les call on null potentiels du code).
          Ca t'oblige à faire une passe sur ton code lorsque tu le compiles.
          C'est un peu vexant au début, mais tu te retrouve avec beaucoup moins de problèmes.

          Pour le reste, le typage avancé et fort, et je pense surtout dans mon expérience en Lisaac et en Ocaml, me permette surtout de faire des choses très avancées, très courte, très propre, qui aurait été des bidouillage infames en Java, voire des fois en Ruby et qui auraient donc été super bugués.
          C'est donc plutôt en rendant le code plus "clair" pour quelqu'un qui a l'esprit assez "théorique" pour comprendre que ça diminue le nombre de ligne, simplifie le code et le rend moins sujets à bug.
          C'est plus une question d'expressivité.

          « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: typage mou

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

      Sauf que ça s'écrit Ada, pas ADA. Si tu en fais la pub, autant savoir l'écrire. Dommage que Ada ait mis si longtemps à avoir l'équivalent de la STL du C++, et que dans l'ensemble le langage évolue si lentement.
  • # Question de feeling...

    Posté par  . Évalué à 6.

    [ceci n'est pas une pub] Je fais du Go depuis quelques temps, et je n'ai pas kiffé autant depuis que j'ai découvert Perl, a long time ago in a galaxy far far way. Really.
    Serieusement, ça me réconcilie avec le code, alors que <mode Fuuuuuuuuu>j'en avais marre d'etre entouré de petit peteux qui s'imaginent tout connaitre parce qu'ils viennent de découvrir comment faire une factory en Java</mode Fuuuuuuuuu>.
    Je recommande à tous ceux qui voudrait essayer de tester GoPlay (dans misc/).
    My 2 cents.
  • # Intéressant pour les idées ... mais non

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

    Je me retrouve en accord avec la plupart des réponses ici à propos du Go. Je pense que Go a de l'avenir non par le langage mais du fait qu'une grosse entreprise est derrière. L'idée de départ est intéressante la gestion faciliter des thread une bonne idée mais globalement pas convaincu.

    Je me suis mis au D, ayant l'habitude de java, c++ et python (et eiffel pour les connaisseurs). J'ai trouvé un langage qui a fusionne les avantages de ces trois langages.
    Toutefois tout n'est pas rose le langage est relativement jeune du coup on croule pas sous les bibliothèque et on découvre de temps en temps des bugs. Ceci est toutefois rattrapé par une communauté proche a l'écoute et dont les fixes arrivent vite une fois détecté.
    Pour moi un langage a suivre le D, j'ai éliminé le scala a cause de la JVM mais j'en convient qu'il est intéressant
    • [^] # Re: Intéressant pour les idées ... mais non

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

      > Toutefois tout n'est pas rose le langage est relativement jeune

      Heu, c'est très relatif, D existe depuis plus de 10 ans et est presque aussi vieux que PHP ou Ruby.

      > Ceci est toutefois rattrapé par une communauté proche a l'écoute

      Mwais, ce n'était pas vraiment mon ressenti. Par exemple, il y a 2 bibliothèques standards en D, incompatibles entre elles.
      • [^] # Re: Intéressant pour les idées ... mais non

        Posté par  . Évalué à 2.

        C'est faux. Ce problème a été réglé.
        D'autres mauvais arguments ?
        Nan sérieusement je suis vraiment fan du langage D et pour moi plutôt que faire du mono il faudrait que la communauté se penche un peu plus sur ce langage. Il ne faut pas oublier que les contributeurs ne sont pas des newbie, par exemple A. Alexandrescu qui est une référence dans le monde du C++.
        Maintenant tout n'est pas rose dans le D monde,par exemple le compilateur gdc est a la traine ce qui est un gros handicap.
        • [^] # Re: Intéressant pour les idées ... mais non

          Posté par  . Évalué à 4.

          > C'est faux. Ce problème a été réglé.

          Dis plutôt que ce problème est en train d'être regler pour D2 (qui il me semble n'est pas encore sorti en version stable), mais que problème restera pour D1 ou la communauté des utilisateurs devant le manque de fonctionnalité de Phobos a realisé une autre 'librairie standard' incompatible techniquement et avec aussi une licence differente de celle de Phobos (une recherche google sur "SHOO's time library" montre bien le bazar résultant).

          Ce qu'on peut résumer facilement en: un *gros* bordel, qui ne donne vraiment pas confiance dans la "plateforme D"..

          Ce n'est donc *pas* un mauvais argument..


          • [^] # Re: Intéressant pour les idées ... mais non

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

            La D2 est stable
            GDC est à jour et marche avec la D2
            Phobos2 est stable
            Tango2 n'a pas fini son portage D2

            Le langage D me séduit bien plus que le Go, syntaxe, maintenant, performance ... que du plaisir

            Note: GDC sera intégré en standard a partir de gcc 4.7
            • [^] # Re: Intéressant pour les idées ... mais non

              Posté par  . Évalué à 3.

              > La D2 est stable

              Ahem, ça dépend de la définition de stable..
              Ma définition de stable, c'est stable comme un compilateur C.
              D2 en est loin..
              La spec est stable, les implémentations .. non.

              Au niveau de la syntaxe D est pas mal effectivement, dommage qu'il ait gardé la syntaxe de la déclaration de variable a la C, heureusement qu'il y a l'inférence de type..

              > Note: GDC sera intégré en standard a partir de gcc 4.7

              ça c'est une très bonne nouvelle!!

          • [^] # Re: Intéressant pour les idées ... mais non

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

            Et la deuxième révision de D2, c'est R2D2 ?
  • # Commentaire supprimé

    Posté par  . Évalué à 10.

    Ce commentaire a été supprimé par l’équipe de modération.

  • # Groland

    Posté par  . Évalué à 1.

    Je suis le seul à avoir lu « groland.org » comme premier lien ?
    • [^] # Re: Groland

      Posté par  (Mastodon) . Évalué à 5.

      Non, mais tu es peut-être le seul à ne pas avoir lu le tout premier commentaire.

Suivre le flux des commentaires

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