Vous pensez que l'herbe est plus verte ailleurs ? Allez donc faire un tour sur The Daily WTF

Passer de Java à Scala – Partie 1 – Le shell !

Passer de Java à Scala – Partie 1 – Le shell !

Pour faire suite à mon premier article où je présentais un aperçu de ce que pouvait être le passage de Java à Scala, je vais entrer un peu plus dans le détail du langage dans ce 1er article d’une série dont le nombre d’articles est encore indéterminé 🙂

Cette fois-ci, on va jouer un peu avec l’interpréteur de Scala !

Retrouvez tous les articles de la série « Passer de Java à Scala »

Lancement du shell

Pour lancer le shell scala, rien de plus simple : ouvrez un terminal et tapez scala

$ scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_77).
Type in expressions for evaluation. Or try :help.

scala>

Commençons par taper une simple opération pour voir ce que ça donne :

scala> 1 + 2
res0: Int = 3

La 2è ligne indique que l’interpréteur a stocké le résultat dans une variable nommée res0, qu’elle est de type Int et qu’elle vaut 3.

On peut rappeler cette variable plus tard :

scala> println(res0)
3

Ou l’utiliser dans d’autres calculs :

scala> 2 * res0
res1: Int = 6

On a maintenant une autre variable, res1, avec la valeur 6. Pour afficher le resultat de res0 * res1, sans l’assigner à une variable, on peut utiliser la fonction println() :

scala> println (res0 * res1)
18

Définir des variables

Il y a 2 façons de déclarer des variables en scala : val et var.

val définit une variable final qu’il est impossible de réassigner plus tard, à l’instar de var qui se comporte comme une variable réassignable par la suite :

scala> var s = "Bonjour"
s: String = Bonjour

scala> s = "Au revoir"
s: String = Au revoir

scala> val s2 = "Hello"
s2: String = Hello

scala> s2 = "Good bye"
<console>:12: error: reassignment to val
       s2 = "Good bye"

Vous remarquez qu’on ne définit pas le type des variables s et s2 : Scala est capable de déterminer quel est le type de variable en fonction de ce qu’on lui assigne.

Si l’on veut être explicite, on peut très bien spécifier le type de la variable en la suffixant de :<type> :

scala> val message:String = "Bonjour"
message: String = Bonjour

A noter que le type String référencé ici est java.lang.String qui est importé implicitement dans tout programme Scala (import java.lang.*). On aurait donc aussi pu écrire :

scala> val message:java.lang.String = "Bonjour"
message: String = Bonjour

On peut également écrire sur plusieurs lignes dans l’interpréteur s’il considère que la ligne en cours n’est pas terminée :

scala> val multiline =
     | "Une instruction sur 2 lignes"
multiline: String = Une instruction sur 2 lignes

Si on se trompe, on peut taper 2 fois sur entrée pour revenir à l’invite de commande :

scala> val oups =
     |
     |
You typed two blank lines.  Starting a new command.

Une commande utile pour réinitialiser les variable stockées en mémoire est la commande :reset :

scala> :reset
Resetting interpreter state.
Forgetting this session history:

val message:java.lang.String = "Bonjour"
val multiline =
"Une instruction sur 2 lignes"

Forgetting all expression results and named terms: message, multiline

Enfin, pour quitter l’interpréteur, on peut taper la commande :quit


Définir des fonctions

Maintenant qu’on a vu comment définir des variables, attaquons-nous aux fonctions :

scala> def max(x:Int, y:Int): Int = {
     | if(x > y) x
     | else y
     | }
max: (x: Int, y: Int)Int

Une fonction est définie par le mot-clé def. Vient ensuite le nom de la fonction (max), les paramètres (x et y) ainsi que leurs types (Int), le type de retour de la fonction (Int) puis la définition de la fonction ( = { .. } )

Dans l’exemple ci-dessus on note une chose surprement quand on vient du Java : la fonction renvoie un entier mais il n’y a pas de mot-clé return ?

En fait, le return n’est pas nécessaire. Scala considère l’écriture d’une expression en fin de fonction comme un return si cela lui semble adapté. Si on veut être explicite, on peut également écrire les return :

scala> def max(x:Int, y:Int): Int = {
     | if(x > y) return x
     | else return y
     | }
max: (x: Int, y: Int)Int

A noter que le type de retour d’une fonction n’est pas obligatoire. En effet, en fonction des valeurs retournées par la fonction, Scala est capable de définir le type de lui-même :

scala> def max(x:Int, y:Int) = {
     | if(x > y) x
     | else y
     | }
max: (x: Int, y: Int)Int

Dernière chose : les moustaches { } ne sont nécessaires que si le bloc de commandes contient plusieurs lignes. Ici on peut écrire l’expression if .. else sur une seule ligne pour faire tenir la déclaration de la fonction en une seule instruction :

scala> def max(x:Int, y:Int) = if(x > y) x else y
max: (x: Int, y: Int)Int

Voyons comment les choses se passent avec une fonction sans paramètres et qui ne retourne rien :

scala> def saluer() = println("Ouaish !")
saluer: ()Unit

On voit que le type de retour de saluer est Unit : c’est l’équivalent en Scala du void de Java.


Exécuter un script Scala

On peut écrire notre programme dans un fichier .scala et le faire exécuter par le shell. Par exemple pour un script qui affiche les arguments passés en paramètre :

var i = 0
while (i < args.length) {
  println(args(i))
  i += 1
}

On obtiendra :

$ scala printargs.scala Scala c'est cool
Scala
c'est
cool

args est la variable contenant les paramètres passés à la ligne de commande. Il s’agit d’un tableau de String : en Scala, les tableaux s’accèdent via des parenthèses et non des crochets.


Itération via foreach et for

La programmation utilisée pour ce script est impérative. Scala s’oriente plutôt vers la programmation fonctionnelle (bien que comme vu à l’instant il est possible de faire de l’impératif).

Les var n’existent pas en programmation fonctionnelle, les val sont la norme. Scala est un hybride mais il faut préférer la programmation fonctionnelle lorsque l’on fait du Scala.

Réécrivons le code ci-dessus dans un style fonctionnel :

args.foreach(arg => println(arg))

On obtient :

$ scala printargs-fonctionnel.scala c'est plus court
c'est
plus
court

On reconnaitra les lambdas intégrées à Java 8.  La différence est que l’assignation se fait via => et non ->.

Pour finir cet article, voyons comment s’utilise le for :

for (arg <- args)
  println(arg)

L’assignation des valeurs se fait via <- . La valeur assignée est une val et non une var, d’où l’inutilité de spécifier val ou var.


Conclusion

Voilà pour cet article sur le shell Scala et sur quelques bases du langage. Dans le prochain article nous ferons joujou avec les classes, objet compagnons, tableaux et collections !

Laisser un commentaire