Sortie de Scala 2.8 !

Posté par (page perso) . Modéré par Benoît Sibaud.
Tags :
21
15
juil.
2010
Java
La version finale de Scala 2.8 est sortie !

Scala est un langage de programmation très évolué. Il se compile en bytecode Java ou en .Net. La compatibilité avec Java est telle qu'il est possible d'utiliser des classes écrites en Java à partir de Scala et vice-versa.

Ce langage intègre de façon naturelle des fonctionnalités issues des langages orientés-objets et des langages fonctionnels. Les apports de la programmation fonctionnelle aux langages objets, plus répandus, sont multiples et deviennent rapidement indispensables une fois qu'on y est habitué.

En particulier, il est maintenant possible d'écrire des codes à la fois très concis, comme en Ruby ou Python, tout en ayant beaucoup plus de sûreté grâce à un typage statique fort. Cela est rendu possible grâce à un système très avancé de gestion et d'inférence des types.

Plus d'infos sur cette nouvelle version dans la suite de la dépêche.

NdM : Le code source de Scala est sous une licence propre au projet mais semblable à la licence BSD. Les nouveautés de la version 2.8.0

  • Nouvelle bibliothèque de collections

  • La bibliothèque de collections fournie avec Scala a été modifiée en profondeur afin d'éviter les redondances de code et pour faciliter l'intégration de nouvelles collections.
    Certaines méthodes prennent maintenant un constructeur de collection en argument implicite ce qui est transparent pour l'utilisateur dans la majorité des cas et permet de faire des choses comme ça :
    scala> val mymap = Map(1 -> "a", 2 -> "b") //On crée une table de hash
    mymap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b))

    scala> mymap.map(_._1) //On récupère la clé de chaque couple dans mymap
    res13: scala.collection.immutable.Iterable[Int] = List(1, 2)

    scala> mymap.map(_.swap) //On inverse chaque couple clé -> valeur dans mymap
    res15: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2))

    Ici on voit que le type de la collection renvoyée par la méthode "map" est différent (List[Int] ou Map[String,Int]) suivant la fonction passée en paramètre (_._1 ou _.swap). Le type le plus adapté est automatiquement choisi !

    Supposons que l'on souhaite forcer le type de retour et obtenir une collection de type Vector[Int] en appliquant la fonction _._1 :
    scala> val b : Vector[Int] = mymap.map(_._1)
    :10: error: type mismatch;
    found : scala.collection.immutable.Iterable[Int]
    required: Vector[Int]
    val b : Vector[Int] = mymap.map(_._1)

    Ça n'est pas accepté, à juste titre, par le compilateur car dans ce cas "map" renvoie une List[Int] et non un Vector[Int]. On peut toujours convertir une List[A] en Vector[A] mais ce n'est pas efficace. Le plus efficace est de faire :
    scala> import scala.collection.breakOut
    import scala.collection.breakOut

    scala> val b : Vector[Int] = mymap.map(_._1)(breakOut)
    b: Vector[Int] = Vector(1, 2)

    "breakOut", une fonction générique comme une autre (rien n'a été ajouté au compilateur), va automatiquement passer à la fonction "map" le constructeur permettant de créer un Vector[Int]. Tout ça de façon statique et type-safe grâce à l'inférence du type de breakOut avec comme contrainte le type de b (Vector[Int]).

  • Nouvelle implémentation des tableaux (Array[T])

  • Je ne rentre pas dans les détails, ceux qui sont intéressés pourront regarder ici : http://www.scala-lang.org/sid/7

  • Spécialisation

  • Java fait la distinction entre les types primitifs (int, double...) et les types objets (qui ont tous pour ancètre commun la classe Object). Quand on utilise des types génériques, le code généré remplace le type générique par le type ancètre commun le plus proche. Sans contrainte sur le type générique, le code généré utilise la classe Object par défaut.

    Exemple : class Vector[A]
    La classe Vector prend un type (A) en argument. Comme celui-ci n'est pas contraint, le code généré considerera le type A comme étant la classe Object.

    Un problème se pose dans le cas des types primitifs : ils n'héritent pas de la classe Object. Pour qu'on puisse créer un vecteur d'entiers, le compilateur fait ce qu'on appelle de l'auto-boxing (et de l'auto-unboxing) : il crée un objet qui englobe le type primitif et c'est cet objet qui est utilisé (car il hérite bien de Object).

    Le problème de cette méthode est qu'elle est plus lente car elle implique la création et la destruction de nombreux objets. C'est ici que la spécialisation devient utile. En écrivant :
    class Vector[@specialized A]
    Une classe Vector sera créée pour chaque type primitif en plus de celle habituelle utilisant un objet. Ces classes spécifiques seront utilisées par le compilateur lorsqu'il le pourra, ce qui devrait améliorer grandement les performances.

    La bibliothèque standard de Scala commence progressivement à utiliser la spécialisation.

  • Valeurs par défaut et arguments nommés

  • Il est maintenant possible de spécifier des valeurs par défaut pour les arguments de méthodes :
    scala> def f(a: Int = 10, b: String) = printf("a: %d, b: %s \n", a, b)
    f: (a: Int,b: String)Unit

    Et il est possible de spécifier les arguments à partir de leur nom :
    scala> f(b = "Yo")
    a: 10, b: Yo

    Ça devrait permettre de remplacer de nombreux cas où la surcharge était utilisée pour obtenir des valeurs par défaut :
    def g(a:Int, b:Int, c:Int)
    def g(a:Int, b:Int) = g(a,b,10)
    devient
    def g(a:Int, b:int, c:Int = 10)

  • Package objects

  • En Scala, les classes ne peuvent pas contenir de méthodes statiques comme en Java. À la place elles ont un "companion object" qui est un singleton dont les méthodes sont statiques. Avant Scala 2.8, la situation était la suivante :
    • les packages peuvent contenir des classes et des objets
    • les objets peuvent contenir des objets, des classes, des alias de type, des méthodes statiques et des champs
    En Scala 2.8, les packages peuvent aussi contenir des alias de type, des méthodes et des champs s'ils sont déclarés avec :
    package object mon.nom.de.package

  • Diverses améliorations dans Scala Swing

  • Scala Swing est un ensemble de classes qui englobent les classes de Swing. Tout est type-safe et beaucoup plus naturel qu'en Java. Exemple :
    import swing._
    val w = new MainFrame {
    title = "Scala demo"
    contents = new Button {
    text = "Pouche mi!"
    }
    }
    w.visible = true

    La gestion des événements se fait naturellement avec du pattern-matching :
    listenTo(mouse)
    reactions += {
    case e: MouseClicked => println("Clic à la position "+e.point)
    }

  • Améliorations de REPL

  • REPL (Read-Evaluate-Print Loop) est une sorte de shell pour Scala, l'équivalent de irb pour Ruby ou ghci pour Haskell. Les exemples de cette dépêche qui comportent le préfixe "scala>" sont des extraits de sessions REPL.

    Ce dernier supporte maintenant la complétion (touche tabulation).

  • Amélioration des parsers combinators

  • Scala dispose d'une bibliothèque permettant de créer très facilement des parsers (un peu à la Flex/Bison) directement en Scala. Avec le support des Packrat parser combinators, les grammaires récursives à gauche sont dorénavant supportées.

  • Support des continuations

  • Un plugin pour le support des continuations est maintenant intégré à la distribution standard. Comme c'est un sujet un peu complexe et qui n'intéressera pas tout le monde, je renvoie ceux qui sont intéressés à http://www.scala-lang.org/node/2096

  • Conclusion

  • Beaucoup de choses nouvelles dans cette version qui a mis des mois avant de sortir. Les prochaines versions devraient sortir à intervalles plus réguliers et plus courts.

    À noter aussi que Martin Oderksy, le créateur de Scala (et accessoirement des "generics" et du compilateur de référence de Java 1.5), a annoncé qu'il allait fonder une entreprise faisant du support pour les utilisateurs de Scala.

    Je recommande vivement à tous les développeurs d'essayer Scala. N'hésitez pas à poser des questions dans les commentaires.
  • # Paris Scala User Group

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

    Et pour les Ile-de-Franciens, je signale l'existence du Paris Scala User Group : http://groups.google.com/group/paris-scala-user-group

    La prochaine réunion devrait avoir lieux en septembre. Le contenu de la présentation n'est pas encore fixé, mais elle concernera sûrement cette nouvelle version de Scala (peut être une présentation du nouveau framework de collections ?)
  • # Licence

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

    Note sur le licence : les clauses sont exactement identiques à celles de la BSD, c'est juste le texte qui les introduit qui change.

    Dans la BSD :
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    Dans la licence de Scala :
    Permission to use, copy, modify, and distribute this software in source
    or binary form for any purpose with or without fee is hereby granted,
    provided that the following conditions are met:


    À part ça, je n'ai vu aucune différence. Je me demande ce qui a pu pousser le ou les auteurs à changer cette formulation.
  • # groovy

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

    Un connaisseur pourrait synthétiser les différences entre Scala et Groovy ?

    Sur la page wikipedia de Groovy je peux lire du concepteur de Groovy : "I can honestly say if someone had shown me the Programming in Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy."
    • [^] # Re: groovy

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

      Je suis assez novice en scala, mais je dirai qu'il n'ont pas grand chose en commun à part la compatibilité avec la JVM.

      Grooy est un dérivé du Java.
      Scala est un nouveau langage avec de nouveaux concepts très profonds.
      • [^] # Re: groovy

        Posté par . Évalué à -3.

        Et on peut ajouter que le créateur de Groovy a dit ceci :
        « I can honestly say if someone had shown me the Programming Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy. »
        http://java.dzone.com/articles/scala-long-term-replacement
        • [^] # Re: groovy

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

          C'est dingue, on peut aussi le lire dans le premier commentaire du fil.

          « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

          • [^] # Re: groovy

            Posté par . Évalué à 0.

            krkr, je suis trop con :) (et/ou je lis trop vite)

            Désolé pour le bruit !
  • # -> et autres symboles

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

    Y'a que moi qui trouve qu'utiliser des ->, => et autres symboles bizarres, ça n'aide pas à la lisibilité

    Ce serait pas plus simple (même si alors ça ressemble fort à du python/ruby) d'écrire ceci:


    val mymap = Map((1, "a"), (2, "b"))


    (Le pire dans ce cas étant que c'est ce qui est affiché par l'interpréteur).
    • [^] # Re: -> et autres symboles

      Posté par . Évalué à 3.

      Tu peux:


      scala> val mymap = Map(1 -> "a", 2 -> "b")
      mymap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b))

      scala> val mymap = Map( (1, "a"), (2, "b") )
      mymap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b))
    • [^] # Re: -> et autres symboles

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

      L'utilisation des symboles peut être très bénéfique. Surtout quand il n'y a pas de mot pour exprimer ce qu'ils représentent.

      Par exemple : http://github.com/scalaz/scalaz/blob/master/example/src/main(...)

      "<*" c'est quand même mieux que "applicativeFunctorWithAnAnonymousLeft"

      Ça demande un temps d'adaptation mais c'est la même démarche que pour les autres sciences : il y a des notations spécifiques au domaine concerné.

      Dans le cas de Map, c'est quand même plus clair de montrer que "b" est associé à la clé "a" avec "a -> b" qu'avec "(a,b)". Si j'avais à représenter une association unidirectionnelle entre deux entités sur une feuille, j'utiliserais plus naturellement une flèche qu'un tuple.
  • # ceux qui connaissent le Ruby devraient plutôt regarder Mirah

    Posté par . Évalué à 3.

    Salut,

    venant de Java puis Ruby/Python, y'a pas longtemps je m'étais posé la question de me lancer sur Scala pour avoir du code rapide mais concis justement.
    Mais j'avais conclu que l'effort d'apprentissage était important. Au contraire, connaissant Ruby et Python, j'avais alors vu que le leader de JRuby, Charles Headius Nutter http://blog.headius.com/ avait lancé un "dérivé" de JRuby, avec aussi la syntax de Ruby mais statique et aussi rapide que Java, tout comme Scala.
    Récemment, ce langage à été renommé Mirah, je ne saurai que trop de recommander, des tronches de chez Google sont aussi sur le coup pour développer des applis sur AppEngine... Certes récent, mais léger et bati sur du solide, avec des leaders qui ont fait leurs preuves et promis à un brillant avenir:
    http://www.mirah.org/

    A bon entendeur...


    Raphaël Valyi
    Founder and ERP Consultant
    http://www.akretion.com
  • # scala <> java pas tout à fait compatibles

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

    "La compatibilité avec Java est telle qu'il est possible d'utiliser des classes écrites en Java à partir de Scala et vice-versa."

    Malheureusement, ce n'est pas tout à fait vrai :

    "En Scala, les classes ne peuvent pas contenir de méthodes statiques comme en Java. À la place elles ont un "companion object" qui est un singleton dont les méthodes sont statiques."

    Il n'est pas possible d'accéder à une méthode statique java, ce qui réduit la compatibilité de certaines bibliothèques.
    • [^] # Re: scala <> java pas tout à fait compatibles

      Posté par . Évalué à 2.

      Pas du tout.
      Il est bien évidemment possible d'appeler une méthode statique Java depuis Scala.
      Et inversement, les méthodes du "compagnion object" de scala sont vues depuis Java comme des méthodes statiques classiques. Il n'y a aucun problème à ce niveau.

      En ce qui concerne la compatibilité Java/Scala, il est même possible d'avoir une classe Java héritant d'une classe Scala, héritant d'une classe Java, ...
      Pour autant il peut y avoir certains problèmes de compatibilité si on utilise certaines possibilités du langage Scala, qui n'ont pas d'équivalent en Java (les "traits" par exemples).
      • [^] # Re: scala <> java pas tout à fait compatibles

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

        Pas sur play framework avec le module scala en tout cas.
        À l'époque que j'avais testé je pouvais lister les méthodes statiques mais pas les utiliser.

        Est-ce résolu depuis peu sur scala ?
        • [^] # Re: scala <> java pas tout à fait compatibles

          Posté par . Évalué à 2.

          Ça n'est pas un problème provenant de Scala à mon avis (en tout cas pas pour les version >= 2.7).
          C'est bien la première fois que j'entend parler d'un problème pour appeler des méthodes statiques depuis Scala.

          Tu peux facilement faire le test avec un petit programme Scala (en appelant par exemple System.currentTimeMillis() ).

          À mon avis le problème provenait plutôt du module scala de ton framework, ou d'un problème de configuration.
  • # Que du bonheur

    Posté par . Évalué à 2.

    Il a l'air vraiment sympa ce language mais si en plus il supporte les continuations c'est du bonheur et en plus du plus il utilise directement shift/reset. Je vais me remettre a croire au père noël moi.
  • # Rétrospective

    Posté par . Évalué à 2.

    Tiens, j'y ai juste repensé : il y a bientôt 5 ans … https://linuxfr.org/~benoar/18916.html (première mention de Scala sur linuxfr il me semble)
    Depuis, le langage a beaucoup gagné en audience, et j'ai pu rencontrer M. Odersky au FOSDEM.
    Longue vie à Scala !
  • # A Scala, je prefere...

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

    Haskell ou Ocaml, pour etre a peu pres 10 fois moins verbeux.
    Et si je ne veux pas de typage fort, alors je fais du Python,
    tout simplement. :)
    • [^] # Re: A Scala, je prefere...

      Posté par . Évalué à 1.

      La JVM est cependant un avantage assez marqué. Scala est clairement fait pour être utilisé par des entreprises du véritable monde réel. Ça n'est pas explicitement le cas de Haskell, et c'est explicitement pas le cas d'OCaml.

      Je dis ça même si, comme toi et beaucoup de gens sans doute, je préfère ces langages et les personnes qui écrivent à leur sujet.
      • [^] # Re: A Scala, je prefere...

        Posté par . Évalué à 3.

        Pfff il faut arrêter de répandre des préjugés... OCaml est utilisé dans le monde réel et beaucoup plus qu'on ne le croit (et pas seulement dans la finance et le Web). OCaml, Haskell et Scala, même combat. Leur seul problème, c'est qu'il n'a a pas Sun ou Microsoft derrière...

        Cela me fait penser à Linux il y a 10 ans : « ce n'est pas fait pour être utilisé dans le monde réel, c'est un truc d'universitaires, si les entreprises ne l'utilisent pas, ça veut bien dire que ce n'est pas sérieux, etc. ».
        • [^] # Re: A Scala, je prefere...

          Posté par . Évalué à 1.

          D'accord. Alors pourquoi le déploiement de projets OCaml est-il toujours si complexe sous Windows ? Pourquoi les contributions extérieures sont-elles toujours aussi peu facilement acceptées par l'INRIA ? Pourquoi des boîtes comme MLState, qui utilisent OCaml, sont-elles obligées de réécrire la moitié de la bibliothèque standard pour avoir quelque chose d'utilisable ?

          OCaml n'a pas le soutien industriel nécessaire. C'est malheureux, mais c'est vrai.

Suivre le flux des commentaires

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