Journal Scala : un langage de prog sympa

Posté par  .
Étiquettes : aucune
1
23
juil.
2005
En Suisse ils ne font pas que du gruyère sans trou, mais aussi un bon langage de programmation "moderne", appelé Scala :

http://scala.epfl.ch/index.html(...)

Il a été développé au LAMP (Laboratoire des Méthodes de Programmation) de l'EPFL (Ecole Polytechnique Fédérale de Lausanne).

Il essaye de concilier programmation fonctionnelle et OO. Il est statiquement typé, et on y trouve pas mal de concepts sympas :
- tout est objet, à la Smalltalk
- il gère la généricité (bon aujourd'hui ça peut paraître classique, c'est vrai)
- les traits, sorte de classes sans état interne, qui permette d'"imiter" l'héritage multiple
- le type d'une variable peut être inféré (localement), ce qui permet de ne pas préciser le type d'une variable à certains endroits
- il possède le moyen de préciser la variance des arguments d'une fonction. Par exemple, un truc qui m'a vraiment étonné, sur les types génériques, on peut préciser que List[String] est un sous-type de List[Object], mais que pour insérer un objet à cette liste, l'argument est contravariant, menant à transformer List[String] en List[Object] si on y ajoute un objet qui n'est pas une sous-classe de String (je pense qu'il prend alors l'ancêtre commun des deux types, j'ai mis Object pour être général)
- et d'autres choses, comme la possibilité d'insérer du XML inline, bref, en l'écrivant tel-quel

Il faut préciser qu'il est compilé pour être exécuté sur une VM Java ou .Net, et qu'il peut utiliser les frameworks de chacun (je pense que ça peut mener à un beau bordel si on doit adapter les classes qui utilisent l'un à l'autre). Je trouve ce point pas super positif, mais bon le langage à l'air vraiment pas mal quand même.

Sinon pour la licence, c'est une BSD-like.

Voilà, j'ai trouvé ce langage lors de recherches sur les différents concepts intégrés aux langages de prog en général, et j'ai trouvé que Scala intégrait un bon paquet de choses que je trouve très utiles & "jolies", programmaticalement parlant. Mais je tiens à préciser que je n'ai pas encore utilisé ce langage, je ne sais pas s'il est bon en pratique, c'est juste ses concepts qui m'ont parus assez intéressants pour en faire un journal...
  • # Interessant

    Posté par  . Évalué à 2.

    ...mais tu peux réexpliquer plus clairement ce passage :


    - il possède le moyen de préciser la variance des arguments d'une fonction. Par exemple, un truc qui m'a vraiment étonné, sur les types génériques, on peut préciser que List[String] est un sous-type de List[Object], mais que pour insérer un objet à cette liste, l'argument est contravariant, menant à transformer List[String] en List[Object] si on y ajoute un objet qui n'est pas une sous-classe de String (je pense qu'il prend alors l'ancêtre commun des deux types, j'ai mis Object pour être général)


    Je ne suis pas sûr d'avoir bien tout compris.
    • [^] # Re: Interessant

      Posté par  . Évalué à 3.

      Bon, je suis vraiment pas doué pour expliquer les choses, alors voici leur exemple :

      class Stack[+A] {
        def push[B >: A](elem: B): Stack[B] = new Stack[B] {
         override def top: B = elem;
         override def pop: Stack[B] = Stack.this;
         override def toString() = elem.toString() + " " +
          Stack.this.toString();
        }
        def top: A = error("no element on stack");
        def pop: Stack[A] = error("no element on stack");
        override def toString() = "";
      }

      Si j'ai bien compris :
      - le [+A] veut dire que le type A est covariant, et que donc une Stack[String] dérive d'une Stack[Object] (attention, je crois que Object n'existe pas, c'est plutot AnyRef ou Any qu'il faudrait utiliser, mais on m'aura compris ... j'espère)
      - push est une méthode polymorphique (= générique), et [B >: A] veut dire que B est un super-type de A, bref, que A dérive de B. Donc, losrqu'on push un élément sur la pile :
      s = s.push[Int](5)
      le type retourné sera Stack[Int] (on peut ne pas préciser [Int], le type est inféré). Puis, si on fait
      s = s.push(new Object())
      (là je n'ai pas précisé [Object]), alors le type renvoyé sera Stack[Object], en bref, notre pile d'Int s'est transformée en pile d'Object. Bien sur, si on ne souhaite pas ce comportement, il suffit que la variable affectée (s) soit du type que l'on souhaite, et une erreur à la compilation sera détectée.

      Bon c'est vrai qu'après on peut trouver la construction de cette pile assez étrange, car le code est vraiment fonctionnel plus qu'objet ici (cette pile est gérée à la manière des liste en Lisp, avec une tête et le reste). Au début j'ai eu du mal à comprendre def top: A = error("no element on stack"); !!!

      Enfin voila, j'espère avoir été plus clair, sinon la page l'expliquant surement mieux :
      http://scala.epfl.ch/intro/variances.html(...)
  • # :)

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

    J'ai eu a utilisé ce langage il y a quelques années (ma promo a servi de beta testeur) et j'ai jamais vraiment accrocher. Le langage était super lent à l'époque :) Il y avait plein de bonnes idées et je sais pas si ça a perçé... Ça ressemblait plus à une surcouche de Java qu'à une langage à part entière ...

    Pour la partie XML, j'ai assisté à une présentation donnée par un des developpeur : http://agenda.cern.ch/fullAgenda.php?ida=a053700&header=none(...)
    C'était aussi très intéressant, mais je dois dire qu'au final j'avais quand même l'impression que ça existait déjà à coté plus ou moins (un des avantages avancé par exemple est d'avoir une vérification du XML pour des pages web)
    • [^] # Re: :)

      Posté par  . Évalué à 5.

      Le langage était super lent à l'époque :) [...] Ça ressemblait plus à une surcouche de Java qu'à une langage à part entière ...

      On dit aussi qu'il n'y a pas de fumée sans feu...

      ( Hop, sur ce, je vais prendre l'air ----> [] )
      • [^] # Re: :)

        Posté par  . Évalué à 3.

        On dit aussi qu'il n'y a pas de fumée sans feu...


        Verse de l'azote liquide ou mets de la glace carbonique à l'air ambiant, et tu verras de la fumée, mais pas de feu.

        Mauvais "On dit que..", ne plus utiliser cet "On dit que..."
  • # et Objective Caml ?

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

    Il essaye de concilier programmation fonctionnelle et OO. Il est statiquement typé, et on y trouve pas mal de concepts sympas :

    Ocaml :-)

    - tout est objet, à la Smalltalk

    le tout objet n'est pas la priorité d'OCaml, car son point fort est de pouvoir avoir un style:
    * fonctionnel
    * impératif
    * objet
    suivant les besoins :-)

    - il gère la généricité (bon aujourd'hui ça peut paraître classique, c'est vrai)

    Hmm, je suis pas sûr que OCaml fasse ça, mais il y a sûrement d'autres moyens d'y arriver s'il ne le fait pas.

    - les traits, sorte de classes sans état interne, qui permette d'"imiter" l'héritage multiple

    Je n'ai pas compris le principe de ce que tu décrit ? tu peux préciser ?

    - le type d'une variable peut être inféré (localement), ce qui permet de ne pas préciser le type d'une variable à certains endroits

    Dans OCaml, on ne précise jamais le type d'une variable, par contre, une fois le type défini par le langage (le compilateur ou interpréteur), il ne peut plus changer.

    - il possède le moyen de préciser la variance des arguments d'une fonction. Par exemple, un truc qui m'a vraiment étonné, sur les types génériques, on peut préciser que List[String] est un sous-type de List[Object], mais que pour insérer un objet à cette liste, l'argument est contravariant, menant à transformer List[String] en List[Object] si on y ajoute un objet qui n'est pas une sous-classe de String (je pense qu'il prend alors l'ancêtre commun des deux types, j'ai mis Object pour être général)

    Si c'est bien de l'invariance, OCaml :-) (le tant bizarroïde ;;)

    De plus, OCaml fonctionne en trois modes:
    * interprété, fonctionne comme tous les langages interprétés, avec un interpréteur ;-)
    * semi-compilé (bytecode), comme java, dans une machine virtuelle caml
    * compilé en natif, dans ce cas, OCaml gagne pratiquement la palme du code compilé le plus rapide (juste en-dessous du C avec le meilleur compilateur/optimiseur qui soit, MS C/C++ 7 - oui je sais, ça fait mal pour nous adorateurs de gcc)

    C'est un langage fonctionnel (ou les fonctions sont des éléments de première classe - aka peut être passé en argument et être le résultat d'une expression), venant de la famille des langages de type lamba calcul (comme ML, bien qu'il ne retienne pas du tout la syntaxe), et de surcroît, c'est français (INRIA).

    A part peut-être une syntaxe un peu plus proche des langages objet 'communs' (comme Ruby par exemple), je ne vois pas l'intérêt de ce langage, ce qui ne veut pas dire que je blâme les inventeur de Scala :-)
    • [^] # Re: et Objective Caml ?

      Posté par  . Évalué à 1.

      Ocaml :-)

      Oui oui je connais, enfin Caml tout court, c'est avec ce langage que j'ai redécouvert les langages fonctionnels (j'avais fait du Scheme il y a quelque temps), j'ai eu droit à un semestre de cours, et j'avoue que ca m'a réfléchir de manière différente sur la programmation.

      - il gère la généricité (bon aujourd'hui ça peut paraître classique, c'est vrai)

      Hmm, je suis pas sûr que OCaml fasse ça, mais il y a sûrement d'autres moyens d'y arriver s'il ne le fait pas.


      En tapant "ocaml generics" sur google, je suis tombé sur ca :
      http://lambda-the-ultimate.org/node/view/804(...)
      Qui parle d'un article sur lequel j'étais déjà tombé. En bref, dans les commentaires j'ai lu que Ocaml gérait le parametric polymorphism (??) et que ca résoudrait le problème. Bon j'ai pas cherché beaucoup. Mais je pense que les generics sont la un peu pour palier le "statisme" des langages OO classiques, et que les langages fonctionnels n'en ont généralement pas besoin.

      - les traits, sorte de classes sans état interne, qui permette d'"imiter" l'héritage multiple

      Je n'ai pas compris le principe de ce que tu décrit ? tu peux préciser ?


      Je viens de revoir leur page pour essayer d'éclaircir mes propos, mais en les relisant je ne comprend plus trop. Ils disent que l'exemple de trait peut etre utilisé dans les mixins, mais en fait ils ne le font pas (pages pas à jour?).
      Ce que je sais sur un trait, c'est que c'est une classe qui ne contient pas de variable d'instance. Ainsi, on peut hériter d'une classe classique et d'un trait (donc c'est de l'héritage multiple) sans que ca pose de problème avec les conflits de variable d'instance, car si on hérite de deux classes qui ont une variable d'instance en commun, ca pose problème. (j'avais commencé une explication avec la problème de l'héritage en diamant en C++, mais je me suis un peu embrouyé et j'ai arrêté ...)

      A part peut-être une syntaxe un peu plus proche des langages objet 'communs' (comme Ruby par exemple), je ne vois pas l'intérêt de ce langage, ce qui ne veut pas dire que je blâme les inventeur de Scala :-)

      Justement, je pense ce qui repousse la plupart des développeurs élevés au C (comme moi ;-)), c'est la syntaxe. Le manque de librairies aussi, mais cela vient du manque de développeurs, et donc de la syntaxe (selon moi, hein). C'est vrai que faire une syntaxe à mi-chemin entre fonctionnel et OO, tout en évitant les problèmes que ca peut impliquer, c'est galère, mais je trouve que Scala se débrouille pas mal sur ce point.

Suivre le flux des commentaires

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