Accueil » Perso, Scala

Le gars qui connaît Scala et celui qui débute

8 décembre 2011 2 941 affichages 36 commentaires

Tag image Scala
Un peu de Scala vite fait pour faire chauffer le CPU :

Soit un numéro IBAN simple, présenté sous la forme d’une grosse chaîne de caractère :
FR7630057410821012122045021

Comment l’afficher à l’écran en le formatant de cette façon ?

FR76 3005 7410 8210 1212 2045 021

Voici un premier bout de code écrit en juillet dernier par votre serviteur :

val iban="FR7630057410821012122045021"

iban.zipWithIndex.map{p=>p match{case(t,idx) if (idx+1)%4==0=>{print(t+" ")} ; case(t,idx)=>{print(t)}}}

// si, si ça marche

Et voici le même code après avoir lu la doc et aussi après avoir vu un email sur la liste du Scala User Group :



for(p < - iban.sliding(4,4).toList){ print(p+" ")}


Conclusion : lisez la documentation avant de vous lancer dans des "expérimentations" pour dire ensuite "dans skala' c'est compliqué".

36 commentaires »

  • Al a dit:

    Sinon tu peux aussi faire ;)
    iban.sliding(4,4).map( _+ " " ).foreach( print )

  • Benjamin Lerman a dit:

    Le meme sans l’espace a la fin:

    println(iban.sliding(4,4).reduceRight(_+" "+_))

  • Al a dit:

    Ok alors tant qu’a faire
    print( iban.sliding(4,4).mkString( " " ) )
    Il n’y a pas a dire, le code review ca paie :)

  • Olivier Hubaut a dit:

    Encore plus simple:
    print(iban.sliding(4,4).mkString( » « ))

  • Olivier Hubaut a dit:

    Damn, grille le temps de lire l’article…

  • Olivier Croisier a dit:

    Et le gars qui connaît Guava :

    System.out.println(
    Joiner.on(\' \').join(
    Splitter.fixedLength(4).split(\"FR7630057410821012122045021\"))
    );

    Et un développeur, même junior, n\’a pas besoin de 6 mois de formation pour arriver à écrire ce code.
    Moi je dis ça…

  • Nicolas Martignole (author) a dit:

    Ouep, pas bête de montrer aussi la version Java.

    Et en Groovy ? Là je suis pas chaud mais ça doit être facile je pense

  • Loic a dit:

    Intéressant! En scala on peut toujours faire des choses simples, et très jolies (très expressives quoi).
    Le seul danger c’est surement que des mecs un peu « chauds » nous pondent des API beaucoup plus tordus pour profiter de toutes les subtilités du langage…

    @Nicolas A ce propos que penses tu de l’API Anorm de Play? Pour une fois je vais critiquer Play (version Scala), je la trouve hyper compliquée avec tout ses « hiéroglyphes » dès qu’on veut faire un truc un peu poussé…

  • Nicolas Martignole (author) a dit:

    @Loic la version actuelle d’Anorm avec les parsers combinators est puissante, mais trop compliquée. Ils travaillent sur une version plus simple pour Play 2.0. Moi je m’y suis habitué, j’ai bossé 5 mois avec et c’est facile. Il faut apprendre le principe des « parser combinators » mais rien de méchant. Il faudrait que je fasse un article sur ce sujet car c’est très riche.

  • Guillaume Saint-Raymond a dit:

    La version en Groovy mais ce n’est pas la plus évidente :
    iban.split("(?<=\\G.{4})").join(" ")

  • Loic a dit:

    Cool c’est une super nouvelle qu’ils simplifient un peu ça!
    Un article sur ce sujet serait très intéressant en tout cas.

  • Fabian Piau a dit:

    En tout cas, je salue le jeu de mot à la fin… si jeu de mot il y a bien… ;)

  • Sébastien Blanc a dit:

    Une autre variante Groovy mais pas non plus vraiment la plus claire :-) (et nécessite une deuxieme variable (output))

    iban.eachMatch(/.{4}/){output=output+ »${it} « }

  • Sébastien Blanc a dit:

    Avec les balises code, c’est mieux
    iban.eachMatch(/.{4}/) {output=output+"${it} "}

  • kawas a dit:

    Pareil en clojure,
    on écrit du code les 1ères semaines et 3 mois plus tard on se rend compte que l’on était un vrai novice :)


    (->> "FR7630057410821012122045021"
    (partition-all 4) (interpose " ") (flatten) (apply str))

  • Matthieu Guillermin a dit:

    Et voilà pour PHP :

    echo implode(" ",str_split($iban,4));

  • Aurélien Pelletier a dit:

    On va oublier la première version de Nicolas, mais ça nous laisse quand même

    1 for(p < - iban.sliding(4,4).toList){ print(p+" ")}

    2 iban.sliding(4,4).map( _+ " " ).foreach( print )

    3 println(iban.sliding(4,4).reduceRight(_+" "+_))

    4 print( iban.sliding(4,4).mkString( " " ) )

    4 manières différentes d'exprimer la même chose dans le même langage, ça doit pas aider pour travailler en équipe ou maintenir le code.

    Je me demande si c'est parce que les librairies de scala sont mal pensées, ou si le problème vient du paradigme fonctionnel ?

  • joseph a dit:

    Et que tout ceux qui voudraient en conclure que scala c\’est compliqué se demandent d\’abord s\’il y a une façon unique de faire une telle chose dans leur langage de prédilection… Et combien même, je ne suis pas certain que cela serait une bonne chose!

    ++

  • Aurélien Pelletier a dit:

    « There is more than one way to do it » c’est le moto de perl un langage qui n’est pas réputé pour sa lisibilité ou sa maintenabilité.

    « There’s Only One Way To Do It » c’est le moto de python un langage qui a quand même meilleure réputation.

    Maintenant chacun est libre d’en conclure ce qu’il veut à propos de scala.

  • Bruno a dit:

    Pour Guava, il faut avoir eu connaissance de cette librairie parmi Apache-Commons et autres, savoir l’integrer, connaitre les API quelle propose …
    De plus Splitter ne fonctionne que pour les String (ou charSequence) alors que :A](Int,Int):GroupedIterator[B]« >sliding fonctionnera sur tout Iterator et pourra donc resservir.

    Je connaissais déjà la fonction sliding pour l’avoir utilisé sur des Lists.

  • blouerat a dit:

    Il y aura un espace en trop à la fin dans les différentes versions proposées. Et d’un point de vu purement on fonctionnel, le mieux c’est de générer la string finale, puis de l’afficher (effets de bord…). Du coup j’aurais une préférence pour un :
    println(iban.sliding(4,4).mkString("", " ", ""))

  • Alexis Agahi a dit:

    C’est fou ca, à chaque fois qu’on parle de Scala, on en arrive au vieux debat du « mon langage pisse plus loin que le tiens ». Il va falloir inventer une variante de la loi Godwin pour les langages…

  • Sébastien Blanc a dit:

    @Alexis A part Aurelien qui trolle un peu, chacun a juste exposé de manière sympathique et ludique la version de chaque language. J’ai trouvé ca très intéressant et je pense que personne ne voulait pisser le plus loin, ca serait bien triste sinon et pas digne d’un dev ;-)

  • Guillaume Laforge a dit:

    Pour la version Groovy, mon premier réfléxe était un simple coup de replaceAll :

    def iban = "FR7630057410821012122045021"
    println iban.replaceAll('(.{4})', '$1 ')

    Il n’y a pas d’espace à la fin comme dans certaines de ces solutions, et surtout… ben replaceAll c’est une méthode de java.lang.String :-)

  • Fabrice Croiseaux a dit:

    Pourquoi ne pas utiliser .grouped(4) au lieu de .sliding(4,4), je crois que c’est fait pour ça. Ce qui donne

    print(iban.grouped(4).mkString(" ")

  • Aurélien Pelletier a dit:

    et hop une 5eme variante !

    @guillaume tu triches, tu connais les expressions régulière ;) http://xkcd.com/208/

  • Alexis Agahi a dit:

    @Fabrice Croiseaux bien vu ! et visiblement c’est le meme code en dessous

    def grouped[B >: A](size: Int): GroupedIterator[B] =
    new GroupedIterator[B](self, size, size)

    et

    def sliding[B >: A](size: Int, step: Int = 1): GroupedIterator[B] =
    new GroupedIterator[B](self, size, step)

  • Loic a dit:

    La version la plus lisible serait pour moi au final

    for(p < – iban.grouped(4).toList){ print(p+" ")}
    ou
    iban.grouped(4).map( _+ " " ).foreach( print )

    @Aurélien Pelletier je connais pas bien python mais en tout cas que je soit Java ou Groovy il n'y a pas une unique façon de faire cette opération…
    Du moment que tu as des API riches sur la manipulation des chaines et des collections tu trouveras toujours plusieurs moyens de faire ce genre de choses

  • Brice a dit:

    @Aurelien Enfin quand même en Java tu peux aussi écrire ce code différemment, les débutants ne connaissent même pas tous les features de Java standard, alors qund tu ajoutes les commons-collection et guava tu te retrouves avec du code très varie, donc il y a exactement le même problème d’homogénéité dans l’écosystème.

    Ce qui est important ce n’est pas la concision du code, c’est sa lisibilité et sa maintenabilité. En Java comme en Scala comme pour tous les langages, et ça franchement c’est aussi le boulot du développeur. Si c’est un newbie, qui sort de l’école et qui n’a fait que des projets jetables, il faut l’amener a ces considérations.

  • Olivier Croisier a dit:

    Ben justement, des trucs qui s’appellent Splitter et Joiner me paraissent plus explicites qu’une méthode « sliding ». Toutes considérations de langages mises à part.

    Sinon j’aime bien la version de Guillaume aussi :)

  • Lorber Sebastien a dit:

    Apres avec du Java/Guava on peut aussi splitter la list en sous listes de 4 elements:
    Iterables.partition( iban.toCharArray() , 4 );

    Au final tous les langages permettent de faire a peu près la même chose sauf que forcement les nouveaux langages s’inspirent du passé et proposent plus de choses nativement… Y a qu’a voir toutes ces librairies java (dont apache commons) qui n’utilisent toujours pas les generics…

    Au final rien ne vous empêche de contribuer sur les libs Java :D

  • Olivier Croisier a dit:

    Et en Haskell :

    byFour :: [Char] -> [Char]
    byFour (a:b:c:d:xs) = [a,b,c,d,' '] ++ byFour xs
    byFour x = x

    Je trouve ça plus lisible que la version Scala :
    for(p < – iban.sliding(4,4).toList){ print(p+" ")}

  • fredb a dit:

    Le but de l’exercice c’est de résoudre le problème avec les primitives du langage, ou, à la limite, les quelques classes de base. A priori, sortir une librairie externe, que ce soit guava ou apache commons, ça sort un peu des clous.
    +1 à la version regexp + groovy ;)

  • Nicolas L. a dit:

    @fredb : le jour ou l’iban est sur un multiple de 4, la solution Groovy générera un bug :)

    A propos de la conclusion de l’article c’est évident qu’il faut lire la documentation, et cette conclusion pourrait être faite pour n’importe quel langage.

  • Gabriel a dit:

    fun([A, B, C, D|Rest)->[A, B, C, D, $\s|fun(Rest)];
    fun(Rest)->Rest;
    Comme en Haskell, quoi :)

    Ou bien :
    I= »FR7630057410821012122045021″.
    lists:reverse ( lists:foldl(fun(Char, Acc)->
    case length(Acc) rem 5 of
    4 -> [Char, $\s|Acc];
    _ -> [Char|Acc]
    end
    end, [], I)).

    La fonction rem :reste de la division..
    On accumule tous les caractères, tous les 4 on rajoute un \s (qui veut dire universellement « espaaace »)
    Et une fois la chaîne de caractères obtenue par accumulation en tête de la liste, on retourne cette liste (lists:reverse).
    Je crois que c’est clair :D

  • Patrick Bernard a dit:

    C’est gentil toutes ces variantes…
    Mais elles nous font combien de cycles horloge?

    C’est une autre poésie… je sais, je sais