Reia, un langage fortement inspiré de Ruby

Posté par (page perso) . Modéré par j.
19
18
déc.
2010
Ruby
Ruby est un langage de programmation génial (je vous assure, je suis totalement objectif quand je dis ça ;-) ), mais qui a quand même quelques petits défauts. On peut par exemple citer la mauvaise prise en charge de la concurrence ou l'absence de rechargement de code à chaud. À l'opposé, Erlang a une syntaxe parfois cryptique mais sa machine virtuelle est très avancée pour tout ce qui concerne les aspects distribués, la concurrence et la tolérance aux erreurs.

Reia est un langage de programmation qui cherche à prendre le meilleur des 2 mondes (licence MIT). Le code en reia ressemble à s'y méprendre à du code Ruby, mais il s'exécute sur la machine virtuelle d'Erlang. Voici à titre d'exemple le très classique Hello World :

"Hello world!".puts()

Pour le moment, il n'y a pas encore de version officielle de reia. Si vous souhaitez l'essayer, il vous suffit de cloner le dépôt git, d'avoir Erlang et Rake installés puis de lancer rake. Pour les rubyistes, il ne devrait pas être difficile de démarrer avec Reia. La plupart des constructions devraient vous être familières :
# Assigner une valeur à une variable

foo = 42
# Créer une chaîne de caractères avec de l'interpolation
bar = "foo vaut #{foo}"
# Ou encore créer une classe
class Baz
def initialize()
"Une nouvelle instance de Baz vient d'être créée".puts()
end
end


Mais il existe aussi quelques différences assez subtiles :
# La création d'un objet n'utilise pas le mot-clé new

baz = Baz()
# Les parenthèses sont obligatoires pour appeler une méthode
qux = [1, 2, 3].reverse # qux n'est ici qu'une référence à la méthode
quux = qux()
# Le mot clé fun permet de créer des fonctions anonymes
courge = fun(n) { n + 2 }
# Il existe des nouveaux types comme les tuples
grault = (1, 2, 3)
  • # Ahhh enfin ! :-)

    Posté par (page perso) . Évalué à 1.

    Enfin un langage qui écrit
    "Hello world!".puts() !
    C'est vrai quoi, "Hello World!" est une chaine, et l'affichage de cette chaine doit être fait par un message de l'objet chaine.

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

    • [^] # Re: Ahhh enfin ! :-)

      Posté par (page perso) . Évalué à 7.

      Si vraiment tu trouves ça bien (ça se discute), c'est possible dans d'autres langages (et pas que pour les chaînes)
      scala> implicit def any2print(a:Any) = new { def puts = println(a) }
      any2print: (a: Any)java.lang.Object{def puts: Unit}

      scala> "choucroute".puts
      choucroute

      scala> 10.puts
      10

      scala> (10,"abc", 0.5) puts
      (10,abc,0.5)

      Pas besoin de parenthèses inutiles (ni du point d'ailleurs).
      • [^] # Re: Ahhh enfin ! :-)

        Posté par . Évalué à 2.

        Les parentheses 'inutiles' montrent au lecteur qu'il s'agit d'un appel de fonction, en plus ici avec effet de bord!, je ne les trouve pas si inutiles..
        • [^] # Re: Ahhh enfin ! :-)

          Posté par (page perso) . Évalué à 2.

          Effectivement on peut les ajouter pour indiquer l'effet de bord (c'est même recommandé dans le "style guide" Scala).
          Dans les autres cas, il est inutile d'indiquer au lecteur qu'il s'agit d'un appel de fonction. Ce serait un champ la syntaxe serait la même. Ça permet de passer des champs en méthode "getter" et vice-versa sans modifier le code utilisateur.
      • [^] # Re: Ahhh enfin ! :-)

        Posté par (page perso) . Évalué à 0.

        Ah, déjà, y'a un mot clé qui ne va pas: implicit.

        Si Reia s'inspire de Python, le "Zen de Python"[*] le dit "Explicit is better than implicit".

        Donc les machins cachés qui sortent d'on ne sait où quand on lit le code sont à éviter.

        http://www.python.org/dev/peps/pep-0020/
        • [^] # Re: Ahhh enfin ! :-)

          Posté par (page perso) . Évalué à 3.

          Les implicits permettent d'utiliser le pattern Pimp-my-library (un peu l'équivalent de la réouverture de classes Ruby à n'importe quel moment) dans un langage typé statiquement.

          Ils permettent aussi d'implémenter un mécanisme de type-classes (à la Haskell). Voir par exemple la bibliothèque Scalaz.

          Les implicits doivent être importés dans le scope pour être utilisés, ce qui limite les risques.

          Bref, je ne les balaierais pas d'un revers de la main simplement parce que quelqu'un a écrit une phrase très contestable pour un langage qui n'a rien à voir ;-).
    • [^] # Re: Ahhh enfin ! :-)

      Posté par (page perso) . Évalué à 10.

      Personnellement je trouve ça "choquant". L'écriture n'est pas selon moi de la responsabilité de l'objet de type chaîne. On affiche sur quoi ?

      C'est pour moi de la responsabilité de l'afficheur de savoir afficher... m'enfin c'est une question d'école.

      Je préfère donc

      display.print("Hello world");

      que

      "Hello world".print();

      Alexandre COLLIGNON

      • [^] # Re: Ahhh enfin ! :-)

        Posté par . Évalué à 3.

        Visiblement l'auteur de reia aime bien les objets 'lourds': d'après l'example, String a une methode puts et d'après son blog une methode 'parse': '2+2'.parse.

        Bof, ce n'est pas le style que je prefere mais bon le langage a l'air intéressant parce que la syntaxe d'Erlang, beurk!
      • [^] # Re: Ahhh enfin ! :-)

        Posté par . Évalué à 4.

        Pour une simple chaine je trouve que c'est plus une question de goût.

        Pour un objet plus complexe, il me semble qu'il vaut mieux écrire sous la forme
        objet.print(display)
        car le display n'a pas à connaitre la structure de l'objet
      • [^] # Re: Ahhh enfin ! :-)

        Posté par . Évalué à 3.

        La remarque de letsyl me parait pertinente d'un point de vue encapsulation si le display doit connaittre tout tes objets, c'est pas terrible comme encapsulation.
        Et '"Hello world".print();' est un raccourci de '"Hello world".print(display)'
        • [^] # Re: Ahhh enfin ! :-)

          Posté par . Évalué à 2.

          Ce n'est pas lié au fait que le display est explicite ou non ?

          Si "string" existe en tant que type primitif, il parait naturel d'envoyer un message print(string) à l'objet display.
          display ne sait traiter que des messages avec des paramètres de type string et n'a alors pas besoin de connaître la structure de l'objet émetteur.
          C'est bien le display qui a la responsabilité d'afficher (et qui sait comment faire, cf. GRASP)

          display.print("une chaine en tant qu'objet primitif")

          Du coup pour s'afficher les objets doivent implémenter un contrat qui est de se décrire sous forme de string en tant que type.
          display.print(monobjetpasfocrémentunestring.getString())

          A fortiori, si mon objet est une classe containeur "String" avec un contrat on obtient
          display.print(mastring.getString())

          Si on se met dans un contexte d'interprèteur où le display.print() est sous-entendu on a bien pour afficher
          display.print(mastring.getString())
          qui s'écrit
          mastring.getString()
          ou encore
          "HelloWorld".puts()

          Après, il faudrait confronter ça a des langages ala Smalltalk où il me semble que tout est objet (pas de type primitifs) pour avoir une vision encore plus puriste et qui s'appriche de ruby mais ca revient au même.
          On envoie une référence à un objet et on invoque sa méthode getString() dans le corps de la méthode display(). (pas besoin de connaître la structure juste le contrat ou même pas cf. duck typing, exception levée, ...)

          Bref tout vient du fait que le display est considéré comme implicite ou non.

          J'ai réconcilié tout le monde ?
    • [^] # Re: Ahhh enfin ! :-)

      Posté par . Évalué à 7.

      C'est vrai quoi, "Hello World!" est une chaine, et l'affichage de cette chaine doit être fait par un message de l'objet chaine.

      C'est beau, les doctrinaires de l'informatique. Mais les méthodes doivent-elles être redéfinissables directement par le pronétariat, ou seulement par une avant-garde chargée de mener le peuple vers l'abolition du système de domination fonctionnel-procédural ? Quelle est ton opinion sur la nécessaire dissolution du Politburo dans une société sans classes ? Critiquer la doxa syntaxique est-il un acte contre-révolutionnaire passible de fatal error devant un tribunal d'exception (après tout de même une auto-critique spontanée obtenue à coups de try...catch dans les gencives) ?
    • [^] # Re: Ahhh enfin ! :-)

      Posté par . Évalué à 2.

      En Ruby, on peut faire:
      "Hello world".display
      La définition doit être équivalente à quelque chose comme:


      module Kernel
      def display(io = $stdout)
      $stdout.write to_s
      end
      end
  • # ...

    Posté par . Évalué à 8.

    Reia est un langage de programmation qui cherche à prendre le meilleur des 2 mondes (licence MIT). Le code en reia ressemble à s'y méprendre à du code Ruby, mais il s'exécute sur la machine virtuelle d'Erlang. Voici à titre d'exemple le très classique Hello World :

    Ca veut donc dire qu'il faut tout réécrire pour reia.

    Il n'aurait pas été possible d'avoir un mode de compatibilité ruby (ie juste une nouvelle vm pour l'existant ruby) ?
    • [^] # Re: ...

      Posté par (page perso) . Évalué à 3.

      > Il n'aurait pas été possible d'avoir un mode de compatibilité ruby (ie juste une nouvelle vm pour l'existant ruby) ?

      C'est possible, mais ça demande un effort plus conséquent, notamment pour supporter tout ce qui est metaprogramming. En tout cas, l'auteur de Reia n'a pas l'air de vouloir aller dans cette direction.
    • [^] # Re: ...

      Posté par (page perso) . Évalué à 5.

      À mon avis non car il y a aussi des différences sémantiques nėcessaires pour coller au modèle de concurrence de Elang. Voir notamment le commentaire associé à l'exemple de classe donné sur la homepage : "Classes (of immutable objects. Once created objects can't be changed!)" Je découvre ce langage par cette dépèche donc je ne fais que spéculer, mais ça me semble coller avec le fait qu'en Erlang les variables ne sont pas non plus modifiables. Cette caractéristique permet d'assurer que les données ne sont pas partagées entre les threads (processus Erlang), ce qui évite d'avoir à utiliser des mutex.

      Voir aussi le commentaire sur l'exemple de méthode terminée par un point d'exclamation: "You can add a ! to the end of any method to rebind the method receiver to the return value of the given method minus the bang". L'objet n'est pas modifié comme en Ruby, mais une copie est renvoyée, même si l'auteur à voulu proposer un sucre syntaxique qui rappelle les bang methods de Ruby.

      PS: Merci Bruno pour cette dépêche. Je débute avec Erlang et je me disais justement l'autre jour que ce serait bien d'avoir des langages plus faciles à écrire portés sur cette VM, comme c'est la cas pour la VM Java. Du coup je constate que je ne suis pas fou, ou plutôt qu'il y a bien plus fou que moi ;)
    • [^] # Re: ...

      Posté par . Évalué à 2.

      > Il n'aurait pas été possible d'avoir un mode de compatibilité ruby (ie juste une nouvelle vm pour l'existant ruby) ?

      Ça existe déjà. Par exemple, jruby tourne sur la JVM et c'est un projet stable et bien avancé (compatibilité Ruby 1.8.7).
  • # Faute

    Posté par (page perso) . Évalué à 2.

    « Si vous souhaitez l'essayez »

    Légère faute ;)
  • # new

    Posté par . Évalué à 6.

    En Ruby, "new" n'est pas un mot clé. Au contraire, c'est une méthode de la classe Class.

    http://www.ruby-doc.org/core/classes/Class.html

    C'est beaucoup plus interressant qu'une construction propre au langage (que ce soit un mot clé "new" comment en Java ou bien une construction syntaxique comme en Reia).
    • [^] # Re: new

      Posté par . Évalué à 2.

      Visiblement Reia emprunte aussi beaucoup à Python, donc sans certitude aucune je dirais que comme en Python "()" est un opérateur donc une méthode ( surcharge d'opérateur ).

      C'est assez pratique ça permet de faire du duck typing entre classes et méthodes, et tout autre objet "callable".

      Donc bref je doute que ce soit "une construction syntaxique".
      • [^] # Re: new

        Posté par . Évalué à 0.

        Euh Ruby et Python sont nés à la même période peu ou prou (4 ans d'écart en fait, ne dit Wikipedia). S'il y a un langage d'inspiration, il s'agit de Perl et de SmallTalk dans le cas de Ruby. Tu es sûr que ce n'est pas Python qui s'inspire aussi de SmallTalk ? :)
        • [^] # Re: new

          Posté par . Évalué à 2.

          Reia emprunte [...] à Python
          Je ne dit pas dans ce message que Ruby s'inspire de Python, même si àhma c'est le cas.

          Voir aussi cette entrevue de Matz [0] (le créateur de Ruby) qui montre clairement que Python est une des multiples sources d'inspiration de Ruby à défaut d'être la seule ou la principale.

          [0] http://linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html
          • [^] # Re: new

            Posté par . Évalué à 1.

            Les emprunts et influences entre langages après leurs naissances sont courants.

            Par exemple, le C++ a beaucoup influencé son père: le C.
            Perl 6 s'est inspiré de Haskell via Pugs.
            PHP 5 a été influencé par Java (ben oui, les classes!).
            etc...

            Les auteurs de langages louchent régulièrement du cote des autres langages pour voir comment "ils font" pour certaines fonctionnalités.

            Donc dire que Matz s'inspirent de Python ne me semble pas anormal. Il doit sûrement s'inspirer aussi de Javascript, Haskell, Scala et autres langages "chauds" du moment.
  • # Python ?

    Posté par . Évalué à 4.

    Bonjour,
    si l'on regarde les "différences assez subtiles" que vous montrez :


    # La création d'un objet n'utilise pas le mot-clé new
    baz = Baz()
    # Les parenthèses sont obligatoires pour appeler une méthode
    qux = [1, 2, 3].reverse # qux n'est ici qu'une référence à la méthode
    quux = qux()
    # Le mot clé fun permet de créer des fonctions anonymes
    courge = fun(n) { n + 2 }
    # Il existe des nouveaux types comme les tuples
    grault = (1, 2, 3)


    On constate que Python a exactement ce comportement :

    >>> class Baz:
    ...    pass
    ...
    >>> baz = Baz()
    >>> qux = [1, 2, 3].reverse
    >>> qux()
    >>> courge = lambda n: n + 2
    >>> grault = (1, 2, 3)


    (Une différence de convention sur le nommage cependant, Python considère qu'un verbe à l'impératif comme "reverse" implique une modification en place, et qu'il faudrait un participe passé ("reversed") pour avoir une copie qui a subie une modification)
    • [^] # Re: Python ?

      Posté par . Évalué à 0.

      Il fallait lire "subi".
    • [^] # Re: Python ?

      Posté par . Évalué à 3.

      L'auteur ne s'ne cache pas sur le dépôt GitHub: Reia is a Ruby/Python-like language for BEAM, the Erlang VM

Suivre le flux des commentaires

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