Journal A mort les boucles

Posté par  (site web personnel) .
Étiquettes : aucune
0
17
avr.
2007
On parle peu d'informatique en ces colonnes en ce moment, ainsi me suis-je dis qu'un bon troll du mardi serait peut être sympa.

Comme je ne savais pas de quoi vous parler, je vais vous faire partager ma haine pour ce qui me torture en tant qu'analyste programmeur vulgus de métier : les boucles.

Je pourrai parler d'inculture informatique dans l'industrie (comme un de mes chefs à qui j'ai appris ce qu'est une regexp ou une table de hashage, ou d'un autre qui m'a répondu lorsque je lui parlais de langage fonctionnel "fonctionnel ? qui fonctionne ?" quand je pense qu'ils sont chefs censés codé et effectivement programmeurs...), mais non parlons de boucles.

Au commencement, il y avait ça (merci Lurker) :

10 print i
20 i = i +1
30 if i< MAX then goto 10

Ensuite, comme vous le savez on a eu
for ( i = 0 ; i< MAX ; i++)
printf("%d\n",i);

ensuite on pourra avoir ça
(1..MAX).foreach {
int i;
print i;
}

Puis (là ça devient beau)
(1..MAX).map print

Je passe la programmation par contraintes.

Alors comme j'ai lancé ma dissertation de but en blanc, je parlerai de 2 sous problèmes.

Le premier est la sous formation. A l'image de l'anecdote que je rapportai plus haut pour pleurer en passant sur votre épaule (des fois c'est dur), on forme les informaticiens bac+2/bac+4, voire les ingénieurs à l'impératif, à java, etc...
Comme ce sont des gens pour lesquels la définition d'une fonction soit est flou, soit est une notion philosophique qui ne sert à rien (souvent les deux), ils vont avoir un peu de mal si on leur propose de coder en Lisp ou en Caml.

De plus, ce sont en général des GENS (selon la définition GCU : http://imil.net/wp/lexique/ ) qui ont pour caractéristique de se contenter de ce qu'ils ont et de ne pas rechigner à réécrire 100 fois la même chose, chaque jour.
Le mot généricité est un mot vaguement philosophique pour eux. Ils s'en approchent parfois, quand le client gueule parce que le projet a un mois de retard et reste effroyablement buggé.

Le second est lié aux langages. Ecrire un map, un fold ou un filter(1) en java, est une gageure, en on code beaucoup de chose en javouille.
J'ai trouvé ici ou là des tentatives, mais c'est syntaxiquement affreux. Je réessaierai un jour avec la réflexivité.


Une autre raison de la profusion de boucles-qui-ne-servent-à-rien est l'absence d'une sorte de SQL objet dans le langage (je parle pour les langages objets).
Kro$oft en a sorti un depuis quelques années, ça s'appelle LINQ, et je pense que ça va faire un carton.
Par exemple j'ai Objet1 contenant une liste de Objet2, contenant lui même une liste de Objet3, Objet3 possède un champ toto, une chaîne.

Je veux tous les objets de type Objet3 que Objet1 contient mais, seulement ceux sur lesquels la fonction Quelconque(String quoi), appliqué au champ Objet3.toto, renvoi true :

select Objet3 from Objet1 where Quelconque(Objet1.listeObjet2.listeObjet3.toto)

Bah non, je dois faire trois boucles.

Pareil, j'ai deux liste d'objets représentant la liste du personnel d'une boite à deux dates distrinctes. Je veux les comparer(une appli d'analyse d'évolution de la masse salariale par exemple), faut que je fasses des boucles... Et je vous dis pas comme c'est casse gueule de refaire une clause where avec un "not in" pour un dyscalculique comme moi...

Je pense qu'il nous faudrait un outil pour générer du code à partir d'une requête du genre. Je vous en reparlerai bientôt, car j'ai commencé à travailler sur la question.

Bref je crois que dans notre croisade contre les bugs, et avant qu'on arrive à faire des compilateurs sémantique (ie. des langages axiomatiques turing complet, en d'autres termes ou l'on se contente de décrire ce que l'on veut, comme en sql (voir un trip perso là dessus : http://wiki.loria.fr/wiki/Lisaac/M%C3%A9talangage ))


(1)http://www.zvon.org/other/haskell/Outputprelude/filter_f.htm(...)
  • # moué

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

    Puis (là ça devient beau)
    (1..MAX).map print


    Ça restera une boucle, et ça n'empêchera pas les boulets de faire des algos en O(n^2) ou même O(n^3)...
    • [^] # Re: moué

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

      oui mais moi, le codeur, je perd pas mon temps à l'écrire. Que ce soit sémantiquement une boucle, je m'en fiche, et je vois rien à en redire, je parle ici de sucre syntaxique, voire un peu plus.

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

      • [^] # Re: moué

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

        D'un autre côté si le map a une vraie sémantique de map fonctionnel sans effet de bord .oO(haskell), ça permet de paralléliser plein de trucs autrement plus facilement qu'avec des threads. Or, il semblerait que ça soit hype en ce moment d'avoir des processeurs multibrol toussa.

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

      • [^] # Re: moué

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

        Oui. Ce que je voulais dire c'est qu'apprendre à réfléchir avant de coder, ça permettrait aux gens de coder mieux. Coder plus efficacement, le but du sucre syntaxique, c'est bien, entre de bonnes mains. Mais ça permet de faire des bêtises plus vite, plus simplement, en s'en rendant moins compte ;)
    • [^] # Re: moué

      Posté par  . Évalué à 2.

      Ça restera une boucle, et ça n'empêchera pas les boulets de faire des algos en O(n^2) ou même O(n^3)...
      Mwouais... Il fut un temps où, les boucles aidants, je faisait du O(n^4) quand j'en avais l'occasion. Depuis cet âge ingrat (mon dieu, ce que j'ai pu faire comme connerie...) j'évite autant que possible les boucles.
      Il n'y a jamais de solution miracle a tout les problème, mais si quelqu'un en a trouvé une, je suis preneur.
      • [^] # Re: moué

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

        - réfléchir :)
        - tester avec de très gros datasets, pas trois items qui se battent en duel
        - profiler les trucs manifestement énormes
        • [^] # Re: moué

          Posté par  . Évalué à 2.

          Et pour ceux qui veulent voir à que ressemble de mode de développement/profiling/optimisation, je les invite à lire dans les archives de la liste de Git. Un dénommé Linus Torvalds y sévit régulièrement et c'est assez marrant de le voir en action.
          • [^] # Re: moué

            Posté par  . Évalué à 4.

            Un exemple? (oui, je sais, je suis feneant :-) )

            Tom
  • # euh...

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

    Ton exemple LINK me fait penser au XSLT ou comment transforler du XML en rtf (dans mon exemple). En gros, tu passes des règles sur les feuilles de ton arbre, et le bidule se débrouille tout seul.

    Il me semble que ruby propose des choses très jolies sur ce thème.

    "La première sécurité est la liberté"

  • # Critique ?

    Posté par  . Évalué à 3.

    Tu critiques les bac +2 et +4 ?
    fais gaffe à ce que tu dis !
  • # javasux

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

    Le second est lié aux langages. Ecrire un map, un fold ou un filter(1) en java, est une gageure, en on code beaucoup de chose en javouille.
    Java : la syntaxe d'un langage de bas niveau associée à la lourdeur d'un langage de haut niveau.

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: javasux

      Posté par  . Évalué à 10.

      Je l'ai toujours dit que java sux.

      D'ailleurs, en version embarquée, ça donne Java Light Edition, soit Java LE. Ce qui prouve bien que java sux.

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

    • [^] # voir aussi

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

      « The Next Mainstream Programming Language: A Game Developer's Perspective » où on apprend (ou pas) que ça serait bien de passer à des langages avec une syntaxe de plus haut niveau que ce que tout le monde utilise pour le moment tout en gardant un typage fort.

      http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/doc(...)
      http://www.cs.princeton.edu/~dpw/popl/06/Tim-POPL.ppt (c'est la même chose normalement, juste que c'est l'original)

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: javasux

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

      Oui, enfin l'introspection toussa tu me diras quel language de bas niveau le permet ;)

      Ceci dit, je te l'accorde, pour faire du java la plupart de mon temps, il y a un énorme manque niveau sucre syntaxique :-/
      • [^] # Re: javasux

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

        Oui, enfin l'introspection toussa tu me diras quel language de bas niveau le permet ;)
        Le C par exemple (c'est en travaux dans glib/gobject en utilisant libffi apparement).

        Ceci dit, je te l'accorde, pour faire du java la plupart de mon temps, il y a un énorme manque niveau sucre syntaxique :-/
        C'est bien ce que je veux dire.

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

        • [^] # Re: javasux

          Posté par  . Évalué à 3.

          A mon gout, la completion/squelette de boucles d'eclipse permet d'alleger une partie de ces tares.

          Maintenant, ca ne fait pas tout, loin de la et c'est vrai que se fader en permanence des for (Iterator it = list.iterator(); it.hasNext();) ca a tendance a me lourder assez vite, en plus polluer le code.

          Et on ne parlera meme pas des if(str == null || "".equals(str)) qui commencent a me donner des boutons.

          M'enfin, pour l'instant, pour faire des grosses applis web, j'ai pas trouve mieux sur la globalite (ie : toute la chaine dev/debuggin/packaging etc).
          Pis ca remplit mon assiette, alors vais pas trop me plaindre non plus...
          • [^] # Re: javasux

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

            Les bibliothèques commons de Apache sont tes amies.

            if (StringUtils.isEmpty(str))

            Bon, ce n'est pas parfait mais c'est déjà ça !
            • [^] # Re: javasux

              Posté par  . Évalué à 2.

              hehe ouais, je sais bien. Sur un serveur d'appli ca passe bien. Mais ca reste relou de devoir importer une lib pour une connerie pareille. Alors que le but de l'api java est justement d'eviter de dependre de libs externes pour des choses de ce genre. Dommage.

              Bref, ca rajoute une dependance, et quand tu partages du code sur plusieurs plateforme (on a une applet et une midlet qui partage l'essentiel du code metier), embarquer commons quand t'as une limite de taille de jar MIDP1/CLDC1 fixe a 50 voire 55ko max, ca devient dur.
              • [^] # Re: javasux

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

                Oui c'est clair ! Ils auraient ajouté à String une méthode statique isEmpty() ça aurait facilité les choses.

                Pour ça j'aime bien la possibilité dans Ruby d'altérer une classe au runtime pour éviter ce genre de problème.
                • [^] # Re: javasux

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

                  Tiens, il ne serait pas possible de remplacer String par une classe qui en dériverait de manière transparente avec un classloader ?

                  pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

                  • [^] # Re: javasux

                    Posté par  . Évalué à 2.

                    Je dirais que c'est possible, mais ca doit pas etre trivial quand meme, pour employer un doux euphemisme.
                    Depend du contexte surtout, dans une appli cliente riche ou un serveur d'appli un tant soit peu consequents, ca doit pouvoir se faire, sur une applet ou un midlet, ca commence a etre violent quand meme (voire impossible pour une midlet, vient de verifier rapidement, pas trouve de reference au ClassLoader). :-/

                    Surtout ca fait 'achement overkill comme methode.

                    Pis jouer avec les classloaders, c'est marrant, mais si ya moyen d'eviter c'est quand meme plus sympa.

                    Si tu controles totalement l'installation du runtime, le mieux serait encore de prendre les sources du runtime, rajouter les methodes voulues et remplacer java.lang.String par ta version dans rt.jar.
                    Payes ta galere quoi.
                    • [^] # Re: javasux

                      Posté par  . Évalué à 2.

                      La définition est
                      public final class String
                      (et c’est pareil pour beaucoup de classes : Integer, etc.).

                      On ne peut donc pas hériter de String (mot-clef final), sûrement « sécurité oblige ».
                      Il faut donc effectivement changer la classe dans rt.jar. Un sacré merdier pour pas grand-chose.
                      (En même temps, la sécurité, c’est bien.)
                    • [^] # Re: javasux

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

                      Si tu controles totalement l'installation du runtime, le mieux serait encore de prendre les sources du runtime, rajouter les methodes voulues et remplacer java.lang.String par ta version dans rt.jar.

                      Très mauvaise idée !! L'un des pilliers de Java est que ton code tourne sur n'importe quelle machine virtuelle de même version.
                      Si tu commences à ajouter une méthode par ci par là, ça va vite être le bordel !

                      Ce qu'il faut faire, c'est passer par le Java Community Process. Ca prend du temps, ce n'est pas certain que les changements seront fait, mais au moins si ça change, ça sera officiel.
          • [^] # Re: javasux

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

            Maintenant, ca ne fait pas tout, loin de la et c'est vrai que se fader en permanence des for (Iterator it = list.iterator(); it.hasNext();) ca a tendance a me lourder assez vite, en plus polluer le code.


            il existe les enhanced loops depuis java 1.5 ce qui donne :

            List<Foo> list;
            ...
            for (Foo f : list) { f.bar(); }


            Et on ne parlera meme pas des if(str == null || "".equals(str)) qui commencent a me donner des boutons.


            Chaîne nulle ou vide c'est différent. Après si la bibliothèque que tu utilise n'indique pas si elle peut renvoyer null ou si elle renvoie une chaîne vide, change là.
            • [^] # Re: javasux

              Posté par  . Évalué à 1.

              kben du java 5, j'aimerais bien en faire...
              mais bon, les specs c'est java 1.3+
              alors les enhanced...

              Chaîne nulle ou vide c'est différent.
              Ca, ca depend du contexte ma caille.

              Quand c'est un param http optionnel, null ou vide, ben c'est pareil, hein.
              Quand c'est un Properties qui te retourne null ou vide...
              Si un cono de la logistique met une chaine a vide, ben on va se faire emmerder par le client, et a juste titre.
              Et dire a ton manager "C'etait marque dans les specs que ca devait pas etre vide, c'est pas ma faute", ben le client il s'en branle, ya une tete qui doit tomber et ya une chance sur deux pour que ca soit la mienne.
              Preferant prevenir que me prendre un tir des 22m en pleine face, je me retrouve oblige de tout tester..

              Après si la bibliothèque que tu utilise n'indique pas si elle peut renvoyer null ou si elle renvoie une chaîne vide, change là.
              Redescend sur terre stp...
              Les chaines tu les utilises pas toujours dans une lib, tu maitrises pas toujours les inputs.
              Tu peux specifier ce que tu veux, mettre les preconditions que tu veux, le peu d'experience que j'ai m'interdit de laisser partir un code en prod avec ce genre de bug potentiel.

              Les libs externes, tu peux pas toujours les utiliser (cf MIDP1/CLDC1 dont certains telephones ne prennent pas de jar de plus de 63ko. Et si tu rajoutes 10-15ko d'artwork, il te reste plus grand chose pour ton code)
  • # Python ...

    Posté par  . Évalué à 5.

    ... et les list comprehension peuvent aider un peu a faire ce que tu veux :
    [o3 for o3 in concat([o2.listOfO3 for o2 in o1.listOfO2]) if quelq(o3)]
    bon evidemment, si t'a pas l'habitude c'est pas tres lisible. Puis la fonction concat n'existe pas faut la coder (encore que pas sur). Mais moi j'aime bien
    • [^] # Perl

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

      Tous les langages un peu évolués savent faire ça hein (et pour ce coup ci, l'autoapplatissement des listes en Perl ne gêne pas).

      grep { Quelconque $_ } map { $_->Objets3 } $Objet1->Objets2

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: Python ...

      Posté par  . Évalué à 2.

      en haskell, en utilisant des compréhensions de liste :
      [o3 | o2 <- listeo1 o1, o3 <- listeo3 o2, predicat o3]

      On peut faire la même chose en ocaml, mais il n'y a pas de sucre syntaxique pour ça (bien qu'il soit possible de le rajouter avec une extension camlp4) :
      filter predicat (concat (map liste3 (liste2 objet1)))

      Dans les deux cas, on considère liste2 et liste3 comme des fonctions qui renvoient les listes quand tu leur donne l'objet.
      • [^] # Re: Python ...

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

        On peut faire la même chose en ocaml, mais il n'y a pas de sucre syntaxique pour ça (bien qu'il soit possible de le rajouter avec une extension camlp4)

        Effectivement, ça a déjà été fait et je crois bien qu'une telle extension sera distribuée avec le camlp4 du nouveau OCaml 3.10 qui sort bientôt.
  • # Ruby

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

    Pour les print, il y a les versions ruby qui s'en rapprochent un peu quand même (et en étant très lisible - mais non, je parle pas de python ;) )


    5.times { |i| print i, " " }
    -> 0 1 2 3 4

    5.upto(10) { |i| print i, " " }
    -> 5 6 7 8 9 10


    C'est pas aussi concis mais je trouve ça vraiment pas mal :-)
    • [^] # Re: Ruby

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

      j'oublais : question lisibilité et compréhension je trouve 1.upto(MAX) largement plus lisible qu'un (1..MAX)
      La première version est lisible telle quelle, la deuxième demande d'interpréter le '..'
      • [^] # Re: Ruby

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

        Le "upto" nécessite de connaitre l'anglais, le "..." est compréhensible par n'importe qui ayant fait un tout petit peu de math.

        Sinon, quelques manières de le dire en Perl.

        print join ' ', 5...10
        map { print "$_ "} 5...10
        print "$_ " for 5...10

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

        • [^] # Re: Ruby

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

          oué enfin pour écrire print, join ou n'importe quel code il faut connaître l'anglais (un minimum)
          et ça reste à mon sens verbeux mais concis

          (mais je me doutais bien qu'on pouvais faire 'mieux' en perl (j'adore perl et ruby... ;) )
          • [^] # Re: Ruby

            Posté par  . Évalué à 4.

            Pour ajouter de l'eau au moulin: en Python, on dirait
            print " ".join(( str(x) for x in xrange(5,11) ))
            Ou plus efficacement:
            print " ".join(map(str, xrange(5,11)))
          • [^] # Re: Ruby

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

            oué enfin pour écrire print, join ou n'importe quel code il faut connaître l'anglais (un minimum)
            Il existe des langages qui n'ont pas de mots clés ou fonctions de base en anglais (les langages de macro de Microsoft Office et OpenOffice sont localisés par exemple) ou même des langages sans mots clés/fonctions faisant partie d'un « langage humain » (bf, APL apparement,...). C'est justement le genre de langage qui est généralement considéré comme « illisible ».

            Il me semble que, quel que soit le langage, il faut de toute façon apprendre un minimum de syntaxe avant de pouvoir coder ou comprendre quoi que ce soit. Il n'y a pas de langage vraiment « intuitif » et essayer d'en créér un est vain (« Build a system that even a fool can use and only a fool will want to use it. »).

            pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

        • [^] # Re: Ruby

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

          les ranges existent aussi en Ruby si on y tient vraiment

          (5..10).each { |i| print "#{i} " }
          (5..10).to_a.join(' ')

          il y a juste le fait que Ruby fait la distinction entre un range et un tableau, d'où le .to_a pour transformer en tableau et pouvoir utiliser .join()

          mais là aussi, rien n'empêche de définir la méthode .join() qui s'appliquerait directement à un range

          class Range
           def join(s)
            self.to_a.join(s)
           end
          end

          on peut alors utiliser ceci sans problème :
          (5..10).join(' ')
          • [^] # Re: Ruby

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

            il y a juste le fait que Ruby fait la distinction entre un range et un tableau
            C'est quoi l'intérêt ?

            pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

            • [^] # Re: Ruby

              Posté par  . Évalué à 2.

              Comme en python je suppose: quelle est la différence entre:
              for i in range(2000000000): print i
              et
              for i in xrange(2000000000): print i

              La première version va essayer de te créer un tableau de 2000000000 entiers, puis de le parcourir. À mon avis, ça a peu de chances de fonctionner de manière optimale :)
              Si tu n'es pas convaincu, essaye ces deux versions dans une console python :p
              • [^] # Re: Ruby

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

                Oui et donc ma question c'est « quel est l'intérêt de range par rapport à xrange » ?

                pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

                • [^] # Re: Ruby

                  Posté par  . Évalué à 3.

                  Je viens de le dire: la première version va te bourrer la mémoire et mettre à genou ton CPU, parce qu'elle va créer un tableau de 20000000 entiers pour ensuite le parcourir
                  La deuxième version va simplement créer un itérateur, qui ne mémorise que l'état courant et qui ne sait rien faire d'autre qu'aller à l'état suivant. C'est plus économique en mémoire et en temps CPU.
                  En gros:
                  >>> x = range(5)
                  >>> print x
                  [1, 2, 3, 4]
                  >>> x = xrange(5)
                  >>> print x
                  xrange(5)
                  >>> print x.next()
                  0
                  >>> print x.next()
                  1
                  >>> print x.next()
                  2
                  ...
                  Remplace 5 par 2000000. Tu vois tout de suite que ton range va sacrément bourrer à la fois ta mémoire et ton CPU, tandis que le xrange ne coutera rien en plus.

                  C'est quelque chose de bien plus général qu'un simple intervalle. S'il est évident qu'un programmeur d'écrira JAMAIS range(2000000), on peut par contre voir par exemple:
                  data = [line.split(',') for line in open('data.csv').read().splitlines()]
                  qui fonctionnera pour des tests basiques, mais qui est plutôt inefficace:
                  - ton fichier est entièrement gardé en mémoire (read())
                  - il est gardé une deuxième fois en mémoire (chaque ligne comme un élément d'un tableau: splitlines())
                  - enfin, il est gardé une troisième fois en mémoire (chque ligne séparée en champ)
                  Tu auras aussi du utiliser 3 fois le contenu de ton fichier pour simplement afficher tous les premiers champs par exemple:
                  - d'abord en lisant entièrement le fichier (le read())
                  - ensuite en itérant sur les données pour les traiter ligne par ligne (le splitline)
                  - ensuite en itérant sur data

                  Avec un itérateur:
                  data = (line.split(',') for line in open('data.cvs').xreadlines())
                  ton fichier n'est lu qu'une fois en mémoire, les données ne dont itérées que si nécessaire: cout mémoire virtuellement nul et efficacité optimale. Si ton fichier fait 300 Mo et que tu ne veux que les trois premiers enregistrements, la première version nacéssitera de parse et de garder en mémoire les 300 Mo. La deuxième ne prendra pas plus de mémoire que si ton fichier faisait 5 Go ou 5 octets, et ne prendra que le temps nécessaire à lire les trois premiers enregistrements

                  La différence, c'est que le premier est un tableau. Le deuxième est un itérateur (plus précisement, un générateur). C'est la même différence qu'entre un range et un tableau. Vois tu l'intérêt de les différencier, maintenant ? :p
                  • [^] # Re: Ruby

                    Posté par  . Évalué à 2.

                    J'oubliais: les tableaux aussi ont leur utilité (parce que si les itérateurs étaient si merveilleux, on utiliserait plus que ça ;)): avec un tableau, on accède très rapidement à un élément quelconque. range(5000)[4999] te répondra immédiatement, xrange(5000)[4999] nécessite de calculer les 4999 éléments précédents. Tu vas me dire, range aussi, pour construire la tableau. Bien entendu, mais si juste après tu as besoin du 4998 ème élément, ce sera quasi-instantanné pour range. Pour xrange, il devra à nouveau recalculer tous les éléme,nts précédents
                    (bon, ça, c'est la théorie, en pratique, xrange peut te calculer immédiatement un élément quelconque, mais c'est une optimisation spécifique à xrange)

                    De plus, avec un tableau, un résultat est calculé une fois pour toutes. Si tu fais 10 itérations sur une séquence, un tableau te calcule 1 fois le résultat puis le met en mémoire. Un itérateur te calculera 10 fois chaque résultat.
                    • [^] # Re: Ruby

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

                      (parce que si les itérateurs étaient si merveilleux, on utiliserait plus que ça ;)
                      C'est peut être pourquoi les langages où il n'existe pas de tableau sont parfois considérés comme merveilleux :)

                      on accède très rapidement à un élément quelconque
                      C'est un travail pour une table de hachage ça (ou même un arbre, qui peut être implémenté par des listes).

                      De plus, avec un tableau, un résultat est calculé une fois pour toutes. Si tu fais 10 itérations sur une séquence, un tableau te calcule 1 fois le résultat puis le met en mémoire. Un itérateur te calculera 10 fois chaque résultat.
                      Et pourquoi le langage ne pourrait-il pas mémoizer (sic) les résultats tout seul ?

                      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

                      • [^] # Re: Ruby

                        Posté par  . Évalué à 3.

                        > C'est un travail pour une table de hachage ça (ou même un arbre, qui peut être implémenté par des listes).
                        Pas forcément. Si tes éléments sont indexés par les premiers entiers (comme un tableau, quoi), il peut être intéressant de tout classer séquentiellement en mémoire (ensuite, tab[i], est équivalent à une simple addition de pointeurs, ce qui est plus intéressant qu'une fonction de hachage, tu en conviendras)
                        oui, je sais, ça convient pas dans tous les cas Pas la peine de me refaire un cours d'algo, là c'est itérateur vs tableau, pas liste vs table de hachage (tableau != liste, de toute manière, et toc ! ;)).

                        > Et pourquoi le langage ne pourrait-il pas mémoizer (sic) les résultats tout seul ?
                        Comment le langage pourrait il savoir ce qui est pertinent de mémoriser ou pas ? (oui, on pourrait s'inspirer des algos de gestion de la mémoire des OS, mais franchement, si tu veux recoder les caractéristiques de ton OS dans le langage, fais du Java ;))
                        • [^] # Re: Ruby

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

                          là c'est itérateur vs tableau, pas liste vs table de hachage (tableau != liste, de toute manière, et toc ! ;)).
                          Précisement. La seule utilisation légitime des tableaux que tu m'as citée peut être remplacée par l'utilisation de tables de hachage qui sont de toute façon une structure de données qui doit être disponible dans tout langage qui se respecte.

                          il peut être intéressant de tout classer séquentiellement en mémoire
                          Il serait sans doute utile que tu revois ton cours d'algo quand même parce que dans une table de hachage, les éléments sont bien contigüs aussi en mémoire (à moins d'utiliser un chaînage externe pour la résolution de collisions mais c'est de toute façon pas une bonne idée).

                          (ensuite, tab[i], est équivalent à une simple addition de pointeurs, ce qui est plus intéressant qu'une fonction de hachage, tu en conviendras)
                          Dans des langages tels que Python, Ruby ou Perl, tab[i] implique plus qu'une addition de pointeurs. Évidemment le temps d'accès à un élément dans un tableau restera généralement marginalement plus efficace que dans une table de hashage (pas la peine de me refaire un cours d'algo non plus :) mais si on peut éviter d'avoir deux concepts très similaires/redondants mais distincts, ça peut être intéressant d'en éliminer un des deux si ça ne pose pas de problème à l'utilisation (ce qui est le cas si le langage a été un minimum pensé pour).

                          > Et pourquoi le langage ne pourrait-il pas mémoizer (sic) les résultats tout seul ?
                          Comment le langage pourrait il savoir ce qui est pertinent de mémoriser ou pas ? (oui, on pourrait s'inspirer des algos de gestion de la mémoire des OS, mais franchement, si tu veux recoder les caractéristiques de ton OS dans le langage, fais du Java ;))
                          Je vois pas comment tu peux implémenter la mémoization au niveau de l'OS mais c'est relativement simple à mettre en place au niveau du runtime d'un langage pas trop mal foutu (même gcc peut le faire pour du C si j'en crois certains attributs de fonctions non standards).
                          http://en.wikipedia.org/wiki/Memoization#Automatic_memoizati(...)

                          pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

                          • [^] # Re: Ruby

                            Posté par  . Évalué à 2.

                            > Il serait sans doute utile que tu revois ton cours d'algo quand même parce que dans une table de hachage, les éléments sont bien contigüs aussi en mémoire
                            Au temps pour moi, je cours me cacher tout de suite, j'arrête pas de sortir des conneries énormes en ce moment..
                            C'est à cause de la chaleur, ça empèche mon cerveau de travailler de manière optimale


                            Pour ce qui est du troll tableau/table de hachage:
                            en ruby, je sais pas (même si ça fait 3 mois que je dit que j'allais m'y mettre, avec le Lisp et l'Objective-C ;)), mais en Python tu as effectivement des tables de hachage dans le langage, et c'est "à peu près" de même utilisation (s'entend: c'est pas la même classe, mais à l'utilisation c'est vaguement la même chose: la notation foo[key])
                            Il faut voir aussi qu'en python qu'avec un tableau tu as un ordre garanti, tandis qu'avec la table de hachage, puisque la fonction de hachage est un machin interne succeptible de changer, tu peux pas garanit que les clefs seront ordonnées comme tu le penses. Les tableaux sont donc fortement utilisés également pour des trucs genre piles et files, et pas seulement parce que c'est "un peu plus" rapide.

                            > Je vois pas comment tu peux implémenter la mémoization au niveau de l'OS mais c'est relativement simple à mettre en place au niveau du runtime d'un langage pas trop mal foutu (même gcc peut le faire pour du C si j'en crois certains attributs de fonctions non standards).
                            Commence pas à tout confondre hein :)
                            J'ai pas réussi à trouver les attributs dont tu parles, mais de ce que j'ai compris de l'article de Wikipedia, c'est simplement du sucre syntaxique pour quelque chose que tout le monde a déjà fait (exemple avec la STL, j'ai la flemme de faire le tableau en C):

                            typedef std::map<int,int> fmap;
                            using std::make_pair;

                            int factorielle(int n) {
                            int f; static fmap res;
                            if(res.find(n) != res.end()) return res[n];
                            if(n == 0 || n == 1) return 1;
                            f = n * factorielle(n-1);
                            res.insert(make_pair(n, f));
                            return f;
                            }


                            C'est donc bien le programmeur qui décide quand il faut mémoriser, pas le langage qui devine tout seul
                        • [^] # Re: Ruby

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

                          Le langage lua ne dispose que d'une seule structure de donnée, la table. La table est optimisée pour des accès type tableau (indices entiers se suivant en mémoire) mais peut aussi s'utiliser avec des clefs de n'importe quel type.

                          par exemple :
                          t[1000000]=true
                          ne va te créer qu'une seule paire clef/valeur alors que :
                          t = {true, false, true, false}
                          va utiliser des accès de type tableau pour ces valeurs.
                  • [^] # Re: Ruby

                    Posté par  . Évalué à 2.

                    xrange(5)
                    >>> print x.next()


                    Traceback (most recent call last):
                    File "", line 1, in ?
                    AttributeError: 'xrange' object has no attribute 'next'



                    xrange(5000)[4999] nécessite de calculer les 4999 éléments précédents.
                    Ha bon pourtant xrange(y)[x]=x, ou j'ai pas suivit quelque chose...

                    Je n'y connais rien en python, mais le xrange a l'air d'etre un simple intervale alors que le xrange que tu decrit serait plutot une liste chainée...

                    D'ailleurs il semble que on ne peut rien affecter dans un xrange :

                    x[2]=4
                    Traceback (most recent call last):
                    File "", line 1, in ?
                    TypeError: object does not support item assignment
                    • [^] # Re: Ruby

                      Posté par  . Évalué à 2.

                      > Ha bon pourtant xrange(y)[x]=x, ou j'ai pas suivit quelque chose...
                      cf:
                      > (bon, ça, c'est la théorie, en pratique, xrange peut te calculer immédiatement un élément quelconque, mais c'est une optimisation spécifique à xrange)

                      Bon, d'accord, pour le reste, je me suis royalement embrouillé, j'admets: j'ai joyeusement mélangé xrange et son itérateur...

                      Il fallait donc lire:
                      >>> x = iter(xrange(5))
                      >>> print x
                      <rangeiterator object at 0xb7c213e0> # C'est mieux, effectivement ;)
                      >>> x.next()
                      0
                      >>> x.next()
                      1
                      >>> for i in x:
                      ... print i
                      2
                      3
                      4
                      >>>

                      > le xrange que tu decrit serait plutot une liste chainée...
                      Alors là pas du tout:
                      - xrange n'est qu'une fonction qui génère des nombres et qui peut fournir un itérateur
                      - le xrange que je décrivait était un itérateur, qui n'a rien à voir avec une liste chainée.
                      En gros: une liste chainée, c'est grosso modo comme un tableau: tu la construits, puis tu l'utilises
                      L'objectif de l'itérateur est de construire les éléments "à la demande" et de ne rien garder en mémoire (histoire de ménager la mémoire, justement). L'intérêt par rapport à la liste chainée est de ne pas avoir à construire des éléments dont on a pas besoin et de garder une empreinte mémoire faible.

                      Pour être imagé, tu peux voir une liste chainée comme une matrice ligne à N éléments, et un itérateur comme une suite récurrente. D'ailleurs, voilà ce que je peux faire avec les itérateurs, qui est impossible avec les tableaux:
                      class naturels:
                      def __init__(self): self._i = 0
                      def __iter__(self): return self
                      def next(self): i = self._i ; self._i += 1 ; return i

                      for i in naturels():
                      if est_premier(i): print i

                      En gros, je viens de faire une sorte de range(0, infinity). Tu remarqueras que l'appel construction de naturels() ne prend ni un temps infini ni un espace mémoire infini.
                      Avec un tableau (ou une liste chainée), tu aurais été obligé de construire un tableau contenant tous les naturels (ça t'aurait pris un temps infini, mais bien heureusement, ta mémoire sera saturée bien avant) avant de pouvoir itérer dessus.

                      Tiens, un exemple amusant qui me vient à l'esprit: c'est équivalent à:
                      class premiers(naturels):
                      def next(self):
                      i = naturels.next(self)
                      if est_premier(i): return i
                      else: return self.next()

                      for i in premiers():
                      print i

                      > D'ailleurs il semble que on ne peut rien affecter dans un xrange :
                      Avec une liste chainée, tu pourrais...
        • [^] # Re: Ruby

          Posté par  . Évalué à 1.

          > Sinon, quelques manières de le dire en Perl.

          > print join ' ', 5...10
          > map { print "$_ "} 5...10
          > print "$_ " for 5...10

          pour les 2 derniers exemple les "$_" sont inutiles (implicites)

          map {print} 5...10
          print for 5...10

          et on peut même encore faire plus court (et finalement plus lisible):
          print 5..10
          • [^] # Re: Ruby

            Posté par  . Évalué à 3.

            >print for 5...10
            >et on peut même encore faire plus court (et finalement plus lisible):
            >print 5..10

            Tu veux dire, même le for est implicite ?
            À ce train là, en Perl, mêne un programme vide fera quelque chose...
            --->[]
          • [^] # Re: Ruby

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

            pour les 2 derniers exemple les "$_" sont inutiles (implicites)
            Non, il y a un espace après le $_.

            pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

      • [^] # Re: Ruby

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

        Hum, pour moi une syntaxe ou tu appelle un membre d'un nombre pour faire un truc c'est vraiment mal....

        (1..MAX).foreach action;

        Est pas si mal en revanche le reste est vraiment bizarre et pas tellement intuitif...

        Ne pas oublier un truc pour vos règle de nommage :
        ObjectAction

        Dans ton 5.upto(10)....
        C'est Objet.Action.Objet

        Mais bon, je suis sans doute pas objectif vu que je viens surtout du monde :
        C/perl/c++/php/bash/sql
        • [^] # Re: Ruby

          Posté par  . Évalué à 2.

          C'est vrai que c'est un peu déséquilibré parce que dans la plupart des langages objets, le concept objet "message" est directement rendu par l'invocation de la méthode de l'objet auquel il s'adresse (On appelle directement la méthode alors qu'en théorie un message est envoyé à un objet qui déclenche la méthode appropriée en reponse ... ou non)
          http://en.wikipedia.org/wiki/Message_passing#OOP
          http://en.wikipedia.org/wiki/Method_%28computer_science%29

          On devrait donc avoir
          Objet1 Objet2
          genre 5 10

          Je suis étonné qu'aucun afficionados de Smalltalk/Squeak ne l'ait encore relevé.
          http://en.wikipedia.org/wiki/Smalltalk#Messages

          Mais bon une fois qu'on a compris le système on y fait plus attention
        • [^] # Re: Ruby

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

          une syntaxe ou tu appelle un membre d'un nombre pour faire un truc c'est vraiment mal


          Pourquoi ?

          J'y vois simplement le concept d'objet poussé un peu plus loin que dans les langages "objets" mais non complètement objets classiques (j'ai rien contre c++ hein, je l'utilise tous les jours, mais ça pue quand même ;) )

          De la même manière, une chaine est aussi un objet
          on doit pouvoire faire un :
          "mastring".each{|char| print char, " "}


          En ruby tout est objet, est c'est ce qui fait qu'il est vraiment sympa je trouve.

          mais c'est sur qu'entre un :
          for(uint i = 0; i < montab.size(); i++) { print montab[i]; }

          et :
          montab.each{|elt| print elt}


          il y a une sacré différence. Un for est quelque chose que je trouve souvent horrible car il n'est relié à rien (je sais pas trop comment ça s'appel, c'est juste un mot clé qui est tout seul dans son coin). Alors que le each, le upto sont lié directement à l'objet qu'on manipule et c'est vraiment plus logique je trouve

          D'ailleurs, j'aurais plutôt du comparer montab.each a une syntaxe du type :
          foreach(elt in montab) { print elt; }


          On voit bien que dans ce cas foreach arrive de nul part alors que le each est réellement une méthode de mon tableau (je ne compare pas les syntaxe mais vraiment la construction logique du langage)

          (oui, tout ça pour dire que je trouve ça logique et que j'aime beaucoup Ruby. D'ailleurs si certains connaissent des langages objets au même point que Ruby ça m'intéresse ;-) )
          • [^] # Re: Ruby

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

            Lisaac*. Tout y est objet, comme en ruby, même le booléen.

            En lisaac, le for est un message de INTEGER

            1.to 10 do { i.print;};

            Il prend en paramètre un BLOCK, c à d, une liste d'instruction, auquel il donne la valeur de i en argument.

            De la même manière, grâce au type block, tu peux faire des map/fold/filter à pas cher.
            Dans COLLECTION :

            - map blc : BLOCK : SELF<- (
            + result : SELF := SELF.create 0;
              lower.to upper do { i : INTEGER;
               result.add (blc.value item i);
              };
             result
            );

            donc ça donnerai

            montab.map { elt : TABLO;
              elt.print;
              };

            Oui faut déclarer un elt, donc c'est plus un foreach en fait.

            Mais tu as ça à la vitesse du C**

            Je me suis amusé à faire joujou avec les listes à la caml, du genre

            let rec toto = function
            [] -> 0 |
            e::[] -> e |
            t::q -> 10+t+toto q;;

            Les fonctions dans COLLECTION :

            - when_empty blc : BLOCK <- (
              blc.value;
            );

            - when_alone blc : BLOCK <- (
            (count = 1).if {
              blc.value first;
            };
            );

            when_list blc : BLOCK <- (
            (count > 1).if {
              blc.value first,(slice (lower+1) to upper);
            };
            );

            Ca permettra de faire :

            + lst : LIST[INTEGER_32].create 5;
            + res : INTEGER_32;
            lst.add 1;
            lst.add 2;
            lst.add 3;
            lst.add 4;
            lst.add 5;

            lst.when_empty {res := 1;};
              .when_alone {
               x : INTEGER_32;
               res := x;
               };
              .when_list {
               x : INTEGER_32;
               y : LIST[INTEGER_32]
               res := 10+x+y.map {x,y : INTEGER_32;   x+y};
              };

            * Oui je sais, je l'avais pas encore faite ;-)
            ** http://isaacos.loria.fr/li_benchs.html

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

            • [^] # Re: Ruby

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

              Il faudra finir de traduire la page de bench en anglais :

              les ko et Mo devraient être kB et MB, le "en -" être "less" et les petites notes (1), (2) et (3) sont intégralement en français. Ou alors ce sont des restes du premier avril et vous avez fait le même poisson d'avril que gmp (arithmetic without SANS limitations).
              • [^] # Re: Ruby

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

                Oui c'est clair que c'est à la limite du honteux, tu n'es pas le premier à me faire la réflexion.
                Modifier ce site hébergé au loria est une horreur (2 ssh coup sur coup, edition avec un vi sur SunOS 5.7 qui déconne, etc...) Donc j'ai la grosse flemme. Normalement il va migrer bientôt, on en profitera pour le nettoyer.

                Je retiens ta correction à l'encre rouge ! ;)

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

                • [^] # Re: Ruby

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

                  <privé>
                  Pourquoi 2 ssh imbriqués ? Le site est dans /local/isaacos/htdocs/ sur loria1 (ou 2) qui possède un magnifique vim6 et est une formidable mandrake (moui, j'exagère sur les adjectifs). Et puis il y a moyen de faire du ssh dans ton vim local de toute façon, donc...
                  </privé>
                  • [^] # Re: Ruby

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

                    <privé>
                    Non, il est plus accessible de loria1 :(
                    Il faut faire un ftp sur bar

                    Peut être de 2, j'essaierai et si ça marche grand merci, car ras le bol des allers/retour en ftp
                    </privé>

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

            • [^] # Re: Ruby

              Posté par  . Évalué à 2.

              Et ya moyen d'avoir ça avec une syntaxe potable ? (désolé, ignorez ça, c'est un réflexe, un instinct de survie qui me pousse à réagir violemment à la simple vue de := )

              Plus sérieusement, Lisaac, j'aime bien le concept, mais la syntaxe me fait fuir. C'est volontaire ou ça vient de moi ? (du genre INTEGER_32, tout en majuscule, je trouve ça moche - et pas pratique à taper surtout. L'opérateur d'affection de deux lettres, je trouve ça chiant au possible aussi).

              Questions vraiment sérieuses (promis cette fois):
              - LIST[INTEGER_32]: le [ ], il est défini comment (et où, surtout): dans le langage, comme en C++ avec un operator[] ou en python __getitem__ ?
              - pour le .when_alone { foo }, comment on sait que ça s'applique sur lst ? C'est du sucre syntaxique du langage ou un truc astucieux de COLLECTION (du genre when_empty renvoie la liste donc le truc équivaut vaguement à lst.when_empty(bloc_1).when_alone(bloc_2))
              • [^] # Re: Ruby

                Posté par  . Évalué à 2.

                Je trouve aussi personnellement que que Lissac a une syntaxe particulierment rebutante. Mais, comme le souligne Moonz qui dit que "j'aime bien le concept, mais la syntaxe me fait fuir", il est important de ne pas s'arreter a la seule syntaxe mais de bien comprendre ce que le langage peut amener de nouveau ou d'interessant.

                En fait cela m'a rappelé une reflexion qu'a eu Wadler lorsqu'il a travaillé à poser les bases de haskell.

                ------------------
                My experience on the Haskell committee caused me to formulate 'Wadler's Law': time spent in debating a feature doubles as one moves down the following list:

                * Semantics
                * Syntax
                * Lexical syntax
                * Lexical syntax of comments
                ------------------

                Je trouve cette reflexion particulierement interessante. Je trouve d'ailleur qu'il est plus souvent question dans ce fil de discussion de syntaxe que reflexion sur la difference semantique des langages et le rapport de cette semantique avec le besion de faire des boucles.

                Ensuite, c'est ma vie ;-), mais j'aime bien la syntaxe d'haskell ;-) , même si c'est ce qu'il y a derriere que je trouve d'encore plus interessant (transparence referencielle, concept des monads, evaluation paresseuse, etc...).

                Je voulais enfin demander à Ontologia ce qu'il pense de la syntaxe de Lissac en dehors de toute autre consideration sur le langage. Je suis curieux et ouvert à son avis car je me demande ce qui peut plaire aux personnes dans cette syntaxe.


                PS : Pour en revenir sur le sujet de ce journal, il est interessant de voir que haskell ne presente tout simplement pas de probleme de boucle tels que presentés dans ce journal (je precise que j'entend ici boucle de controle au sens imperatif) car le langage n'en permet pas
                (meme si il est possible de construire certaine fonction qui denote le fonctionnement de telle boucle, via les monades, mais bon).
                • [^] # Re: Ruby

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

                  La Wadler's Law m'a fait hurler de rire, c'est particulièrement bien vu ! ;-))

                  Qu'est-ce qui me plait dans la syntaxe de Lisaac ?

                  Déjà mon propre historique a pu influer :
                  Basic à 7 ans
                  Pascal à 15 ans
                  C (mais pas longtemps) à 18 ans
                  A suivi une période où programmer m'emmerdait plus qu'autre chose, principalement à cause des boucles, j'ai plutôt passé du temps à découvrir Linux, bref...

                  J'ai été très marqué par Pascal, qui m'a beaucoup marqué, c'est pour cela que j'aime le ':='
                  Je déteste le concept du = et ==
                  Un égale '=' mathématiquement, c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. Point barre.
                  Un égale est donc une opération
                  'a * 'a -> bool
                  Ca doit donc servir aux tests et à rien d'autres.

                  Le reste c'est de la bidouille.

                  Pour les majuscules, je m'y suis fait, c'est une décision ferme de Benoit, qui y est très attaché, et l'impression que le langage nous gueule dessus choque des gens habitué à communiquer en chat, ce qui n'est pas du tout dans sa culture, d'où le fait que ça ne lui ait jamais effleuré l'esprit.

                  Par contre j'adore la syntaxe à mots clés, je trouve ça géniale

                  une_matrice.mult_by_matrix_and_by_scalar(autre_matrice, un_reel);

                  Bof


                  une_matrice.mult_by_matrix autre_matrice and_by_scalar un_reel;

                  C'est plus clair déjà, mais mon exemple est très mauvais.

                  A l'utilisation, et pour faire du java, du caml, du perl et parfois du C++ (arrrrrrg, je hais ce langage), bah à relire, ya pas photo, c'est de très loin le plus clair et immédiatement compréhensible.

                  En plus la grammaire de Lisaac est minuscule (20 règles), et elle se maîtrise en 1h.

                  Enfin le langage est très puissant, le type Block permet de faire des choses halucinantes, et dans la version quiva sortir, que je teste déjà, il y a ma feature que je réclamai : la possibilité qu'une fonction rende plusieurs valeurs, comme dans les langages fonctionnels.

                  Je ne parle même pas des perfs.

                  Un langage qui peu se targuer d'être un sur-ensemble de SmallTalk (moins la réflexivité, pour le moment) avec la vitesse du C, c'est quand même génial.

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

                  • [^] # Re: Ruby

                    Posté par  . Évalué à 1.

                    C'est rigolo, mais je te trouve plutot radicale et vehement dans tes avis.
                    Ne le prend pas mal hein, c'est juste la maniere dont tu defend certains avis :
                    ------------
                    Ca doit donc servir aux tests et à rien d'autres.

                    Le reste c'est de la bidouille.
                    ------------
                    Je déteste le concept du = et ==
                    ------------

                    Or je parlais du fait que justement
                    ------------
                    Je trouve aussi personnellement que que Lissac a une syntaxe particulierment rebutante.
                    ------------
                    mais que j'etais ouvert aux argument de personne qui la trouve bien, et c'est d'ailleur pourquoi je te demandais ton avis (je me permet de te tutoyer aussi)
                    C'est pour quoi je te trouve dur et radical envers des gens qui partent justement du fait qu'il 'deteste' la syntaxe de Lissac.
                    Mais bon, ceci n'est que digression et j'entend bien tes arguments :-)

                    Cependant, quelque petites choses :
                    ----------
                    J'ai été très marqué par Pascal, qui m'a beaucoup marqué, c'est pour cela que j'aime le ':='
                    ----------
                    vi, tout a fait d'accord, c'est important dans un langages imperatif d'avoir fait cette distinction avec le '=' de la logique ou des maths (je me demande en fait si il s'agit bien du meme ? je n'arrive pas encore a me decider)

                    -----------
                    Je déteste le concept du = et ==
                    Un égale '=' mathématiquement, c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. Point barre.
                    Un égale est donc une opération
                    'a * 'a -> bool
                    Ca doit donc servir aux tests et à rien d'autres.
                    -------

                    justement c'est la que je decroche, si justement on considere que '=' c'est mathematique (c'est une reflexion binaire réflexive, symétrique, transitive, antisymétrique. ) e.g. f (x) = x * x, je ne vois pas necessairement pourquoi ca ne servirait qu'au test et rien d'autre ???

                    prend le cas du lambda calcul. si tu dit que
                    f (x) = x + x (x etant un reel par exemple)
                    ce n'ai pas pour faire quelque test que ce soit, mais juste pour definir la fonction f (de type R -> R ).

                    mais c'est la meme chose si tu dis
                    ma_variable = 42
                    si on considere que ma_variable est un variable mathematique , non ?
                    ainsi
                    f(ma_varaible)
                    sera juste reduite en
                    ma_variable * ma_variable
                    il n'y a donc ni affectation (pour laquel l'operateur ':=' qui a ete crée pour ca est bien plus parlant ), ni test.

                    et d'aileur en fonctionnel on peut aussi avoir besion du ==
                    is_zero n = n == 0
                    ensuite le (truc avec trois barre qu'on utilise en marth et que je ne sais pas ecrire ici :-) ) serait peut etre plus judicieux mais pas utilisable en ascii donc je le trouve tres bien ce == pour un test d'egalité.
                    d'ou ma reponse : je n'ai rien contre = et == bien au contraire.


                    ----------------------
                    Pour les majuscules, je m'y suis fait, c'est une décision ferme de Benoit, qui y est très attaché, et l'impression que le langage nous gueule dessus choque des gens habitué à communiquer en chat, ce qui n'est pas du tout dans sa culture, d'où le fait que ça ne lui ait jamais effleuré l'esprit.
                    ---------------------

                    Je pense aussi pour ma part qu'il est important qu'un langage contraigne le codeur, et meme si peut penser que cela le limite, c'est plus souvent pour son bien (et surtout le bien de l'ensemble de gens qui code dans ce langage et qui donc ont un besoin imperieux de partager certaines convention critique de lecture/ecriture du code)


                    --------------------
                    la possibilité qu'une fonction rende plusieurs valeurs, comme dans les langages fonctionnels.
                    -------------------

                    Heu, je serais plutot en desaccord, ou je ne connais pas de langage retournant plusieur valeur. Peux tu m'eclairer la dessus car en reflechissant a quoi cela pourrait ressembler, je ne m'en fait pas du tout une idée possitive.


                    voila, au plaisir



                    • [^] # Re: Ruby

                      Posté par  . Évalué à 2.

                      prend le cas du lambda calcul. si tu dit que
                      f (x) = x + x (x etant un reel par exemple)
                      ce n'ai pas pour faire quelque test que ce soit, mais juste pour definir la fonction f (de type R -> R ).

                      Oui mais justement, en maths "f(x) = x + x" c'est pas une déclaration de fonction, c'est pas grand chose. Pour déclarer une fonction on fait ça proprement (Soit f : x -> x + x) ou avec une équation (Soit f telle que pour tout x, f(x) = x + x), mais on balance jamais "f(x) = x + x", c'est pas rigoureux.

                      Heu, je serais plutot en desaccord, ou je ne connais pas de langage retournant plusieur valeur. Peux tu m'eclairer la dessus car en reflechissant a quoi cela pourrait ressembler, je ne m'en fait pas du tout une idée possitive.

                      Il parle sans doute des tuples (let proches x = (x + 1, x - 1)) qui permettent de renvoyer des aggrégats d'objets de types potentiellement distincts, et alors ce n'est pas vraiment "plusieurs valeurs en même temps", c'est juste une valeur qui en contient plusieurs autres, et qui est légère (syntaxiquement) à manipuler (pas comme un struct ou un tableau ou...).
                      • [^] # Re: Ruby

                        Posté par  . Évalué à 1.

                        ---------
                        Oui mais justement, en maths "f(x) = x + x" c'est pas une déclaration de fonction, c'est pas grand chose. Pour déclarer une fonction on fait ça proprement (Soit f : x -> x + x) ou avec une équation (Soit f telle que pour tout x, f(x) = x + x), mais on balance jamais "f(x) = x + x", c'est pas rigoureux.
                        ---------

                        Oui effectivement le terme definir n'etait peut etre pas le plus adapté (j'ai penser à denoter ce qui me paraissait meilleur mais 1) n'etant pas plsu sur 2 ) toruvant cela un peu pompeux , je gardais definir).

                        Cependant, j'ai ecris
                        f x = x + x

                        car, je reprenais l'exemple de ce qui se fait en haskell.
                        pour parler de ce que je connais en haskell, et cela semble propre selon ce que tu dis, on aurait pu ecrire :

                        f :: a -> a
                        f x = x + x (pareil que f (x) = x + x)

                        (c'est presque ce que j'ecrivais a l'ecole me semble t'il)
                        ou meme

                        f :: forall a. a -> a
                        f x = x + x

                        mais dans les faits je trouve bien aussi qu'un langage INFORAMTIQUE me trouve tout seul le type de la fonction que j'ai ecrit ou me dise si le type de la fonction n'est pas bien typé, ambigue, ou qu'il a besion d'information complementaire.

                        Apres tout meme si ce n'ai pas tres rigoureux, je n'imagine pas qu'un mathematicien ne se permette pas de temps a autre et lorsqu'aucun doute n'est permis, d'ecrire ce genre de chose ;-)

                        f (x) = a x² + b x + c
                        delta = b² - 4ac

                        mais je me trompe peut etre.

                        toujours est il que dans le cadre d'un langage inforamtique je trouve tres agreable la maniere dont on peut 'poser' ces fonctions, et encore plus magique le fait que celles ci soient referentiellement transparente , c'est a dire exemptes de tout effet de bord.
                        Je ne suis pas mathematicien et j'ai (et continue) de coder en C++ mais haskell m'a veritablement apaisé dans ma maniere de coder et considerer les problemes informatiques (que ceux ci soient bas niveau ou haut niveau, l'important reste de toujours penser dans les termes de ce problemes (et d'ailleur le c/c++ est difficile pour ca mais java / etc ne s'en sortent pas toujours tellement mieux ) ).


                        pour les tuples en retour je suis d'accord avec toi , ca reste une valeur de retour unique (ou je n'ai pas bien saisie alors)
                  • [^] # Re: Ruby

                    Posté par  . Évalué à 2.

                    Petite correction: son nom est Philip Walder.
                • [^] # Re: Ruby

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

                  Moi aussi la syntaxe de lisaac me semblait pourris. Mais en fait, il y a _très_ peu de règle à comprendre pour tout faire.

                  Le c _semble_ simple. Mais la gestion/déclaration des types est catastrophiques. En C++, c'est pire.

                  "La première sécurité est la liberté"

                • [^] # Re: Ruby

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

                  Pour la postérité, voici la première formulation publique de la loi de Wadler que j'ai trouvé : http://www.informatik.uni-kiel.de/~curry/listarchive/0017.ht(...)

                  WADLER'S LAW OF LANGUAGE DESIGN

                  In any language design, the total time spent discussing
                  a feature in this list is proportional to two raised to
                  the power of its position.

                  0. Semantics
                  1. Syntax
                  2. Lexical syntax
                  3. Lexical syntax of comments

                  (That is, twice as much time is spent discussing syntax
                  than semantics, twice as much time is spent discussing
                  lexical syntax than syntax, and twice as much time is
                  spent discussing syntax of comments than lexical syntax.)

                  pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

              • [^] # Re: Ruby

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

                Et ya moyen d'avoir ça avec une syntaxe potable ? (désolé, ignorez ça, c'est un réflexe, un instinct de survie qui me pousse à réagir violemment à la simple vue de := )

                Plus sérieusement, Lisaac, j'aime bien le concept, mais la syntaxe me fait fuir. C'est volontaire ou ça vient de moi ?(du genre INTEGER_32, tout en majuscule, je trouve ça moche - et pas pratique à taper surtout. L'opérateur d'affection de deux lettres, je trouve ça chiant au possible aussi).


                Tu n'es pas le premier :) voire ma réponse à Brouillon.

                - LIST[INTEGER_32]: le [ ], il est défini comment (et où, surtout): dans le langage, comme en C++ avec un operator[] ou en python __getitem__ ?

                [ ] signifie que LIST est un objet (ya pas de classe en lisaac je le rapelle) ayant pour objet générique INTEGER_32 dans le cas présent.

                La définition de LIST est LIST[E], C'est comme un Vector en Java si tu veux.

                - pour le .when_alone { foo }, comment on sait que ça s'applique sur lst ? C'est du sucre syntaxique du langage ou un truc astucieux de COLLECTION (du genre when_empty renvoie la liste donc le truc équivaut vaguement à lst.when_empty(bloc_1).when_alone(bloc_2))

                LIST hérite de COLLECTION (logique s'en est une)
                Je défini la méthode .when_alone dans l'objet COLLECTION, comme défini plus haut.
                Tous les fils en héritent.

                lst étant une liste, c'est un vulgaire appel de méthode.

                BLOCK est un objet "suite d'instructions avec paramètres d'entrés sortis (0,n)(0,n)"

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

              • [^] # Re: Ruby

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

                Pour ce qui est des majuscules, perso, j'ai rapidement pris l'habitude du CAPS LOCK.
                Concernant la syntaxe, elle est très simple et très logique, je te conseille de regarder de plus près car Lisaac est un langage passionant (même si le compilateur v0.1 est un peu limité, mais le 0.2 devrait arriver vite il paraît)
            • [^] # Re: Ruby

              Posté par  . Évalué à 1.

              Lisaac*. Tout y est objet, comme en ruby, même le booléen.
              En lisaac, le for est un message de INTEGER

              1.to 10 do { i.print;};

              Justement, je trouve pas ça si génial que ça moi. Avec ta méthode, du point de vue du sens, le for est un truc qui concerne la première borne : c'est sa méthode qu'on utilise, et à laquelle on donne la deuxième borne et le bloc en arguments (c'est pas forcément la bonne terminologie, mais c'est pas grave).

              Moi, je trouve ça laid. Je vois pas pourquoi dans un for, il y aurait une asymétrie entre la première et la deuxième borne.
              Dans l'idée, je trouve beaucoup plus joli d'exprimer le for comme une fonction qui dépend des bornes et du bloc :
              let for debut fin bloc = ...

              En Ocaml/Haskell par exemple, on peut faire ça pour pas cher. Si on ne fait pas d'effet de bords, le "for" n'a à priori pas grand sens, mais imaginons que le for fonctionnel renvoie la liste des valeurs générées par le bloc à chaque itération :
              let rec for low up bloc =
              if low = up then []
              else bloc low :: for (low + 1) up bloc

              En Haskell, si on crée un alias de for nommé "to", on peut même faire des contorsions syntaxique amusantes, par exemple
              1 `to` 10 $ bloc
              (On peut faire pareil en OCaml si on donne un nom d'opérateur à for : 1 >> 10 $ bloc, par exemple)

              Je pense que cette asymétrie forcée est un des grands problèmes de l'objet.
              • [^] # Re: Ruby

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

                Moi, je trouve ça laid. Je vois pas pourquoi dans un for, il y aurait une asymétrie entre la première et la deuxième borne.
                Dans l'idée, je trouve beaucoup plus joli d'exprimer le for comme une fonction qui dépend des bornes et du bloc :
                let for debut fin bloc = ...


                /me espère pas se gourrer dans ce qui suit :

                En général, on utilise for pour deux choses : soit parcourir un tableau, soit pour simplement faire une iteration

                Dans le cas d'un parcour d'un tableau (une liste, un vecteur, ...) on ne devrait jamais à mon sens utiliser de for mais utiliser des constructions du type
                montab.each()

                Dans le cas d'itération (et donc là il y a une certaine disymétrie), écrire 1.to(10) ne me choque pas vraiment mais on peut très bien remplacer par une écriture du type : (1..10).each
                Dans ce cas il n'y a aucune disymétrie. Mais pour des itérations partant de 0 (comme c'est souvent le cas en info) le mieux reste nbIter.times qui est franchement plus logique je trouve, il colle beaucoup mieux à l'esprit qu'on a des itérations.


                note : sinon, dans les trucs pas logique, pourquoi certains utilisent des for(;;) ?
                Mieux vaut à mon sens utiliser dans ce cas un while(true) (même si ça fait la même chose...), non ?
                • [^] # Re: Ruby

                  Posté par  . Évalué à 1.

                  Dans le cas d'un parcour d'un tableau (une liste, un vecteur, ...) on ne devrait jamais à mon sens utiliser de for mais utiliser des constructions du type
                  montab.each()


                  Une liste, c'est un tableau ? hérétique ! :p

                  Je suis pas vraiment convaincu par l'utilisation des each() à tout vent :
                  - quand on une liste, on fait souvent des manipulations un peu complexes (récursives, toussa), qui sont bien représentées par les map, fold_left et fold_right, mais pas vraiment par each. Évidemment, il y a toujours des cas d'itération simple, mais je pense qu'ils sont largement minoritaires et que ça ne vaut pas le coup de mettre l'emphase dessus
                  - quand on a un tableau, on fait plus que juste le parcourir linéairement (sinon, on utiliserait une liste) : on a souvent besoin de l'indice, et on se retrouve souvent à modifier la case en question. Donc ça demande déjà pour avoir un truc un peu utile de passer deux argument au each : l'indice et la valeur. À ce moment là, le each est déjà assez lourd pour qu'un for soit syntaxiquement au moins aussi agréable

                  Par exemple :
                  tab.each { |i,v| tab[i] <- v + tab[(i + 1) % len] }
                  for i from 0 to len - 1 do { tab[i] <- tab[i] + tab[(i+1) % len] }

                  Dans ce cas très simple, je suis pas convaincu que le each soit plus simple à écrire et à lire (j'ai pris une syntaxe pseudo-ruby au pif, mais ça ne change pas grand chose je pense), il n'apporte pas grand chose, à part une gestion implicite des indices (c'est bien) et un paramètre supplémentaire contenant la valeur de la case actuelle (je suis pas convaincu que le rapport réflexion_supplémentaire/gain_lisibilité soit intéressant).

                  L'avantage principal des itérateurs, si j'ai bien compris, c'est qu'on peut les utiliser de manière plus ou moins transparente sur plusieurs type de données différent (tableaux, tables de hachage, listes à la rigueur). Dans l'idée c'est bien, mais en pratique je trouve que les structures de données que l'on manipule en même temps sont suffisamment différentes pour ne pas avoir besoin de méthodes de manipulations communes : si on commence à implémenter each sur un arbre binaire, c'est qu'il y a un petit problème de conception en général.

                  Dans le cas d'itération (et donc là il y a une certaine disymétrie), écrire 1.to(10) ne me choque pas vraiment mais on peut très bien remplacer par une écriture du type : (1..10).each

                  L'asymétrie n'est pas tant syntaxique que sémantique (hum, je connais pas assez la sémantique pour parler de ça, mais là je pense que c'est vrai ^^) : dans son exemple l'objet auquel on envoie un message, c'est 1, et 10 n'est qu'un argument. C'est fondamentalement asymétrique.

                  À mon avis, l'écriture (1..10).each bloc suggère plus une fonction curryfiée où (each 1 10) est une fonction prenant un bloc et lui appliquant l'itération, qu'un appel objet.
                  • [^] # Re: Ruby

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

                    juste rapidement (manger, toussa ;-) )

                    Une liste, c'est un tableau ? hérétique ! :p

                    Non non, j'ai pas voulu dire ça ;-)
                    Simplement que je rencontre souvent du code où pour parcourir une liste un for i++ est utilisé (oui, il m'arrive de lire du mauvais code... :( )

                    sur le principe du each / for, je ne parlais pas forcément du plus simple à écrire/lire mais ce qu'il me semble le plus correct au niveau de la représentation qu'on peut en avoir (je sais pas trop comment dire, mais sur le fond plus que la forme quoi). Il me semble plus logique dans le cas d'un parcour d'un élement de manipuler d'abord cet élement plutôt que de sortir un artefact tout fait qui en réalité est purement inspiré de langages non objets (voir même de contraintes machines, assembleur toussa)

                    À mon avis, l'écriture (1..10).each bloc suggère plus une fonction curryfiée où (each 1 10) est une fonction prenant un bloc et lui appliquant l'itération, qu'un appel objet.

                    En fait je voyais ça comme (1..10) qui crée un tableau [1, 2, 3 ... 9, 10]
                    et donc le each se rapport sur l'ensemble et non une fonction prenant un bloc et donc dans ce cas c'est un appel objet. (note : je me trompe peut-être, je ne suis pas allé voir comment ça marche à l'intérieur)
  • # vrais programmeurs

    Posté par  . Évalué à 5.

    Ouais, mais les boucles c'est de la programmation structurée et...
    "Les vrais programmeurs ont horreur de la programmation structurée. La programmation structurée est pour les névrosés contrariés qui nettoient leurs bureaux, taillent leurs crayons, rangent leurs affaires et rentrent à l'heure pour manger."
  • # Qu'est-ce que ça fout là ?

    Posté par  . Évalué à 3.

    Non mais oh ! tu te crois où ?
    ceci n'est pas un site d'information généraliste, mais sur les logiciels libres.

    C'est où ?...
    ... ah oui ici [ ]
  • # "condition statements considered harmful" serait un bon titre

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

    http://www.acm.org/classics/oct95/ contient une copie de l'article de Dijkstra sur le goto et ses dangers.

    Maintenant, une tres rapide considération algorithmique permet de dire que tout programme optimal contient au plus 1 saut inconditionnel ( tout autre saut inconditionnel pouvant etre linearisé moyennant insertion du code appelé ).
    Donc, tous les autres sauts sont soumis à conditions.

    Il devient donc interressant de considerer non pas les boucles, sauts comme risqué mais ce qui conditionne ces boucles et sauts.

    la relecture de l'article de Dijkstra en gardant a l'esprit cela, permet de vois un sens nouveau non pour les differents types de sauts abordé mais sur le concept meme des conditions sous-jacent à tout saut.

    Il serait judicieux d'ecrire un nouvel article exposant le probleme des explosions combinatoire des cas à traiter lors d'insertion de series de conditions et de poser le reel probleme de la quasi totalité des langages de programmation qui introduit la notion de condition comme etant une notion explicite et inherante au langage : le cas le plus flagrant reste les soit disant langage objet dont les codes sources utilisent massivement les if & co alors que la quasi totalité des problemes peuvent se resoudre par les fameux concepts de la programmation objets que sont l'héritage ( multiple ou non ), l'encapsulation et autres abstractions ...

    l'essentiel des bugs ne sont ils pas essentiellement des problemes de conditions mal gérés ? ( verification de la taille d'une allocation, verification d'une allocation, verification de droits, ... )

Suivre le flux des commentaires

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