Agrémentez votre JavaScript avec CoffeeScript 1.0

Posté par  (site web personnel) . Modéré par Xavier Teyssier.
Étiquettes :
11
28
déc.
2010
Technologie
CoffeeScript est un langage qui se compile en JavaScript (licence MIT). Il vise à proposer une syntaxe alternative, plus agréable, au JavaScript, mais reste très proche de celui-ci au niveau de la sémantique.

Par exemple, le code coffee suivant :
square = (x) -> x * x

square 42

se compilera de la façon suivante en JavaScript :
square = function(x) {

return x * x;
};
square(42);

Ainsi, CoffeeScript permet d'éliminer les caractères ou constructions disgracieuses du JavaScript pour n'en garder que les bonnes parties. Une autre volonté derrière CoffeeScript est de rester proche du JavaScript. Cela permet de débugger facilement du JavaScript généré par coffee, d'autant plus que le code en question est correctement indenté et passe JS Lint sans avertissement.

CoffeeScript existe depuis un an et vient de passer en version 1.0 pour Noël. Son utilisation se répand (exemples de projets écrits avec CoffeeScript : un client Riak, une bibliothèque pour scanner des chaînes de caractères, un équivalent de Rack pour Node.js et un jeu de tanks). Le succès de CoffeeScript est tel que le comité d'EcmaScript, Brendan Eich en tête, travaille à améliorer la syntaxe du JavaScript en s'inspirant de CoffeeScript de manière ouverte.

Aller plus loin

  • # Règles de portée

    Posté par  . Évalué à 10.

    Comme déjà discuté sur reddit [1], je trouve que les règles de Coffeescript sur la portée des variables sont mauvaises. C'est décrit dans la partie "Lexical scoping and variable safety" de leur site : http://jashkenas.github.com/coffee-script/#lexical_scope

    Because you don't have direct access to the var keyword, it's impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you're not reusing the name of an external variable accidentally, if you're writing a deeply nested function.

    En pratique, cela vient du fait qu'il n'y a pas de construction pour dire où une variable est déclarée/définie/liée : si j'ai bien compris, ils préprocessent le code ensuite, et choisissent la portée minimale relative à l'ensemble des occurences de la variable. Il est donc impossible d'utiliser deux variables ayant le même nom.

    Je trouve que c'est un mauvais choix de conception, parce qu'il fait dépendre la signification de chaque bout de code de l'ensemble des variables qu'il a dans sa portée (et pas seulement de celles qui sont utilisées en pratique dans ce code). Comme déjà débattu au sujet d'Erlang [2], ça réduit la maintenabilité, rend plus difficile les déplacements de code et le raisonnement local sur le code.

    [1] http://www.reddit.com/r/programming/comments/er0qj/coffeescr(...)
    [2] http://linuxfr.org/comments/1193101.html#1193101

    Bref : garder les bonnes parties, peut-être, mais ils rajoutent aussi des trucs douteux. Depuis la mort des bindings dynamiques de Lisp, je pensais qu'on avait atteint un consensus relativement global sur le comportement des déclaration de variables, mais on dirait que non.
    • [^] # C'est pas Coffescript mais javascript le problème.

      Posté par  . Évalué à 0.

      L'idée est peut être mauvaise mais son but est justement de palier un "défaut" du javascript. Puisque ses règles de portés sont déroutantes voir exotiques (comme dit plus bas), c'est en début de fonction qu'on déclare toutes les variables de manière à maintenir une meilleure lisibilité et éviter les surprises...

      Javascript a de vilains défauts. Malgré des similitudes syntaxique avec le C, les règles sur la porté sont bien différentes (pas de porté de bloc toussa). S'imposer cette règle limite les dégâts.
      • [^] # Re: C'est pas Coffescript mais javascript le problème.

        Posté par  . Évalué à 3.

        Il ne me semble pas que les règles de portée de Javascript soient si diaboliques. Les règles sur `this` sont un peu bizarre (mais ce n'est pas une règle de portée à proprement parler, c'est une règle sur le passage implicite d'un paramètre), et les règles sur `var` sont médiocres, mais honnêtement `var` ne me paraît pas plus mauvais que la méthode Coffeescript. Par ailleurs la bonne solution aux problèmes de portée a déjà été mise en place, c'est le `let` ajouté par Mozilla, qui se comporte tout à fait comme il faut (JavaScript 1.7 : we finally got variable binding right !). Évidemment IE6 ne le supporte pas...

        Il me semble qu'il y a deux solutions différentes de celle choisie par CoffeeScript :
        - accepter les limitations de JS<1.7 en proposant un mécanisme de définition de la portée d'une variable (règle le problème du shadowing) en précisant (par avertissement ou carrément erreur) qu'il ne peut être utilisé qu'en début de fonction, et pas de n'importe quel bloc; c'est honnête, simple et ça marche plutôt bien
        - utiliser un préprocesseur pour générer "le bon comportement" dans chaque bloc même pas de fonction, ce qui revient à émuler le comportement de `let`; c'est plus compliqué mais plus puissant aussi

        Dans le deuxième cas, si on met dans un bloc local `local x` (par exemple), l'implémentation pourrait par exemple choisir en interne un nom frais (du genre `x32`) et utiliserait ce nom à la place de `x` dans le bloc concerné. N'étant pas un spécialiste de Javascript, je ne peux pas garantir que ce soit la meilleur façon de faire, mais cela me semble très raisonnable pour commencer (un soucis que je vois est que la génération à la compilation de nouvelles variables locales étonner les gens qui font n'importe quoi avec l'introspection, comme afficher la liste des variables définie dans le bloc et leur valeur).


        En fait fondamentalement je trouve que la solution de Coffeescript est pire que `var`. La plupart de leurs modifications se limitent à une sorte de sucre syntaxique local qui rend une construction donnée plus facile à utiliser. Là, ils empêchent l'accès à une construction déjà existante (var), et considèrent comme bénéfice ce qui est en fait un défaut important (impossibilité de name shadowing), qui a un effet global et non local sur la sémantique du programme. Dans la logique d'une surcouche légère, il serait bien plus cohérent de permettre aux gens d'utiliser localement la construction `var` explicitement, s'ils en ont envie, et d'inférer tout seul comme ils le font actuellement dans les autres cas.
        • [^] # Re: C'est pas Coffescript mais javascript le problème.

          Posté par  . Évalué à 4.

          > Par ailleurs la bonne solution aux problèmes de portée a déjà été mise en place, c'est le `let` ajouté par Mozilla, qui se comporte tout à fait comme il faut (JavaScript 1.7 (...)

          2006, donc

          > Evidemment IE6 ne le supporte pas...

          IE6 il est sorti disons euh 5 ans avant.... en 2001.

          et sinon, qui d'autre que Firefox 2 et 3 le gère actuellement ?
          • [^] # Re: C'est pas Coffescript mais javascript le problème.

            Posté par  . Évalué à 3.

            Tu as raison, 'let' est actuellement une extension spécifique à Mozilla. J'espère que ça va bientôt changer, parce que c'est quand même un atout indispensable pour la programmation civilisée en Javascript.

            Ceci dit, c'était dans ECMAscript 4 (la proposition de standard abandonnée depuis, car trop réformiste), et ça a de bonnes chances d'aller dans Harmony (le nouveau standard) : Brendan Eich parle sur cette question d'un "strong consensus" :
            http://wiki.ecmascript.org/doku.php?id=harmony:let
  • # Ah !

    Posté par  . Évalué à 7.

    Pourquoi ne pas avoir garder une syntaxe C-style (ou C++) ?

    Quand je vois les exemples, ca me semble peu intuitif.

    Que JS soit affreux niveau syntaxe (j'en souffre occasionnellement), d'accord, mais là, il faut en plus rentrer dans une grammaire exotique.
    • [^] # Re: Ah !

      Posté par  . Évalué à 2.

      Tout ce qui n'est pas de type C est exotique pour toi ? Il existe des tas d'autres trucs pourtant, et très utilisés.

      Perso la syntaxe "->" pour les fonctions est très naturelle, et j'arrive à lire sans trop de soucis les exemples simples. Ca introduit des trucs importants pour un langage moderne, comme les extensions qui sont un bonheur pour travailler sur des collections, par exemple, tout en polluant au minimum la lecture par des caracères ou des mots clés inutiles, à première vue.
      • [^] # Re: Ah !

        Posté par  . Évalué à 2.

        python, perl, c, c++ ont une syntaxe relativement conventionnelle et efficace.

        Tu as jeté un oeil sur CoffeeScript ? C'est typiquement un cas où je n'innoverais pas pour faciliter l'adoption - JS est *déjà* exotique, et c'est un cauchemar.

        Je différencie tout à fait le cas où les fonctionnalités et/ou le paradigme sont bien servis par une grammaire adaptée - comme dans ton exemple. Mais là, ce n'est pas exactement ce qui caractérise JS.
        • [^] # Re: Ah !

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

          >> python, perl, c, c++ ont une syntaxe relativement conventionnelle et efficace.

          Autant j'adore Perl, autant, là, LOL¹.

          >> Tu as jeté un oeil sur CoffeeScript ? C'est typiquement un cas où je n'innoverais pas pour faciliter l'adoption - JS est *déjà* exotique, et c'est un cauchemar.

          J'ai découvert CoffeeScript en mars, et ça m'a tout de suite fait dire « hey, en fait, on peut faire du javascript sans se prendre la tête ! Enfin une syntaxe intuitive ! Ça me donne envie d'essayer, ça se présente pas mal du tout ! »
          Comme quoi, l'intuition, c'est pas universel…



          ¹ : et t'as de la chance que les balises HTML "blink" ne soient pas valides.
        • [^] # Re: Ah !

          Posté par  . Évalué à 2.

          J'ai peur de ne pas comprendre ce que tu dis. JS est très proche de C niveau syntaxe.

          C'est quoi les trucs exotiques que tu reproches ici ?
  • # Gardez le meilleur ! suite et fin?

    Posté par  . Évalué à 2.

    Merci pour ce papier.

    J'ai eu l'occasion de lire le bouquin de Douglas Crockford il m'a vraiment donné l'impression qu'il est possible de faire quelque chose de beau avec ce langage.

    Je suis resté sur ma faim... une impression d'inachevé avec ce bouquin. Le sous langage annoncé tout au long du bouquin n'a jamais réellement été décrit. D'un coté des bases du langage (les "bons éléments"), sans jamais d'utilisation concrète et de l'autre les éléments à ne pas utiliser.

    Coffescript est peut être l'illustration que j'attendais.
  • # À quand

    Posté par  . Évalué à 1.

    le noyau Linux réécris en JavaScript ?

    Knowing the syntax of Java does not make someone a software engineer.

    • [^] # Re: À quand

      Posté par  . Évalué à 10.

      Ça va venir, une chose à la fois.

      Tout d'abord, il faut réécrire le noyau en C++.

      Ensuite, le convertisseur C++ vers Java n'est pas encore fait.
      Une fois cette étape réalisée, on aura un noyau en Java, ce qui est une bonne base pour convaincre les décideurs pressés d'investir dans le projet.

      L'argent récolté servira à acheter un distributeur de coca-cola, payer des consultants qui justifieront l'achat de ce distributeur, et financer un sous-projet externalisé: Java-to-Lisp.

      Un développeur essaie de rallier Stallman pour pousser le projet de convertisseur Lisp vers OCaml.

      Et il se trouve que Ocamljs permet de compiler du code Ocaml en Javascript.

      Tu auras alors ton noyau en Javascript.

      Étant donné la complexité du projet, et pour maximiser les chances de trouver les développeurs concernés par les morceaux de code incriminés, les rapports de bogues seront remontés sur Facebook et leur existence signalée sur Tweeter.

      Prochainement, une dépêche sur l'état d'avancement de la chose.
      Si tout va bien, le noyau Linux sera en Javascript avant la sortie de Hurd.

      ------------------------------------> [ ]
      • [^] # Re: À quand

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

        >> Un développeur essaie de rallier Stallman pour pousser le projet de convertisseur Lisp vers OCaml.

        Ça m'étonnerait que ça marche.
        1/ Stallman veut pousser Guile, pas OCaml
        2/ Le compilo OCaml est sous QPL, non compatible GPL.
        • [^] # Re: À quand

          Posté par  . Évalué à 1.

          je crois encore moins en Guile qu'en Hurd. c'est dire.
          • [^] # Re: À quand

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

            T'as tort…
            Guile est un langage de très bonne qualité (en version dev. La version stable pue, si j'en crois ce que le dev ou un de ses proches m'a dit il y a quelques mois).
            • [^] # Re: À quand

              Posté par  . Évalué à 1.

              from http://www.gnu.org/software/guile/guile.html, "Guile is an interpreter for the Scheme programming language".
              donc c'est du LISP en fait, c'est ça ?
              si oui, du coup, je vois pas comment on peut y croire ou pas, puisque ça existe et que c'est utilisé dans des "Successful and long-lived examples in the free software world are GNU Emacs and The GIMP".
              • [^] # Re:Àquand

                Posté par  . Évalué à 2.

                Oui et non, guile est effectivement utilisé dans gimp mais pas dans emacs (c'est du elisp). Ces exemples sont là pour illustrer le fait que pour qu'un
                logiciel puisse perdurer il faut qu'il soit facilement extensible donc scriptable.

                Le but de guile est de devenir le langage officiel de script de tous les logiciels GNU.
                Et c'est pas gagné...
                • [^] # Re: À quand

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

                  > Le but de guile est de devenir le langage officiel de script de tous les logiciels GNU.
                  > Et c'est pas gagné...
                  Enfin, à la base, il était prévu de faire des convertisseurs de differents langages vers Scheme/Guile. Mais ça n'est pas encore effectif.

                  "One of the goals of Guile is to allow other languages to be translated into Scheme and thence into portable byte-code; thus Guile would effectively be a language-neutral runtime environment. This goal has not been fulfilled yet, though various attempts have been made: a dialect of Scheme essentially differing only in its C-like syntax; a translation of Emacs Lisp; a Tcl converter motivated by tkWWW; and something roughly resembling the Logo programming language."

                  Source : http://en.wikipedia.org/wiki/GNU_Guile

                  Il existe aussi js2scheme mais ça n'a vraiment pas l'air très actif (7 ans depuis la plupart des derniers commits) : http://sourceforge.net/projects/js2scheme/
  • # Compilateur vers Javascript

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

    Dans un monde idéal, les navigateurs devraient intégrer une machine virtuelle (à la JVM) qui permette d'éxécuter du code écrit en n'importe quel langage dans une "sandbox". C'est ce que tente de faire le projet native client : http://code.google.com/p/nativeclient/

    Puisque le monde idéal n'est pas encore là et que le seul langage compris par les navigateurs est Javascript, il serait intéressant de pouvoir compiler n'importe quel langage vers du Javascript. On pourrait ainsi écrire son application web en Python, C++ ou Haskell suivant l'humeur et ensuite déployer le "binaire javascript". Une rapide recherche Google m'a fait découvrir le projet "emscripten" qui permet de convertir du bytecode LLVM (donc à priori n'importe quel langage pouvant être compilé pour LLVM) en Javascript :
    http://code.google.com/p/emscripten/

    Est-ce que quelqu'un a des expériences avec ces projets (ou d'autres allant dans le même sens) ?
    • [^] # Re: Compilateur vers Javascript

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

      Oui, mais non :

      Javascript is not a typed language so it should come as no surprise that there are no specific integer or floating-point types, no short, long, byte, double, or any other type other languages use to define numbers. All numbers in Javascript are 64bit (8 bytes) floating point numbers which yields an effective range of 5e-324 (negative) to 1.7976931348623157e+308 (positive).


      http://www.hunlock.com/blogs/The_Complete_Javascript_Number_(...)

      Que tous les nombres soient de base des Float 64bits doit poser des problèmes de perfs (jeux, crypto) que l'on compense avec des grosses machines mais ça reste un léger problème, non ? (Et aussi si on a besoin de précision)
    • [^] # Re: Compilateur vers Javascript

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

      Pour le python -> javascript, il y a pyjamas (http://pyjs.org/) dont j'avais déjà parlé dans un commentaire il y a un moment.
    • [^] # Re: Compilateur vers Javascript

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

      Au moins deux compilateurs Scheme -> JavaScript.

      http://www-sop.inria.fr/indes/scheme2js/
      http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Dumpin(...) -> jss

      Un problème est que je ne suis pas si sûr que tous les langages se compilent *efficacement* vers JS. Suffit que le langage que je compile ait une conception de l'objet complétement différente de JS pour qu'on doive au final réinventer tout le protocole objet en JS (exemple : héritage multiple à compiler vers héritage simple ? simple vs multiple dispatch ?)
      Quid aussi du code qui se base sur la sémantique officielle du langage ? (genre, si mon nombre dépasse ((2^23)+42), alors il bascule en mode big-int, et le test de la ligne 314 devient alors faux, ce qui lance un autre calcul, qui blahblahblah…
    • [^] # Haxe

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

      Sinon on a Haxe, qui permet avec un seul langage, très propre, typé objet, etc, de compiler vers une pluralité de langages tels que le Javascript, PHP, ActionScript (ce pour quoi il a été conçu à la base), C++...

      Plutôt que de rajouter une couche de script sur un langage de script comme le fait CoffeeScript (étant moi-même développeur Javascript, amha je ne vois pas trop l’intérêt ; une fois que l'on a bien saisi tous ses rouages, Javascript est un déjà un très bon langage de script), personnellement je préfère tirer le langage vers le haut, avec entre autres une couche objet digne de ce nom et un typage fort.

      Haxe est robuste (il a déjà plusieurs années d'existence et d'utilisation en production), Open Source et multiplate-formes (et français, pour la petite histoire).
      > http://haxe.org/doc/intro
      • [^] # Re: Haxe

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

        À part son problème de scope js est effectivement excellent.

        jquery avec son usage des selecteurs et des fonctions anonymes donne une surcouche très agréable car précise et concise qui n'est pas sans rappeler du ruby. La possibilité de morpher les objets à chauds et sympa.

        Entre coffeescript et jquery, je garde jquery. Et justement pour éviter les collisions de noms de variables, j'évites de polluer le namespace en mélangeant trop de librairies :)

        Sinon, HaXe c'est amusant en le lisant on a l'impression de déjà le connaître : il fait penser à du C++ du php et autre. J'ai été surpris de pas voir les tableaux associatifs en données de bases, mais je suppose que c'est les anonymous qui doivent être utilisées à la place.

        Juste pourquoi tout le monde refait son langage?

        Mon préféré c'est celui là :
        http://ooc-lang.org/

        - pas de ;
        - objet ;
        - compile en C ;
        - supporte les modules ;

        Si on remplaçait le C par ce langage on pourrait peut être regarder vers le futur :)
        • [^] # Re: Haxe

          Posté par  . Évalué à 2.

          Je ne comprends pas pourquoi tu opposes CoffeeScript et JQuery, il n'y a aucun rapport entre les deux. L'un est une surcouche au javascript, l'autre est une librairie, tu peux écrire du CoffeeScript qui se sert de JQuery de manière complètement transparente, vu que ton CoffeeScript sort du js, j'en ai encore écris hier.
          • [^] # Re: Haxe

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

            D'ailleurs le site de coffeescript utilise les 2. J'ai toujours un peu peur des collisions de namespaces. Mais c'est vrai que ça change des
            $("input[type=text]").each(function (el) { el.value="default" } ) de mettre (el) -> el.value=default

Suivre le flux des commentaires

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