Langage Scala [1ère partie]

En quelques démos, nous allons illustrer l’intérêt (et la puissance) du langage Scala. Ces démonstrations sont réalisées sous Windows avec Eclipse Helios et le plugin scala.
Vous dites encore un nouveau langage à apprendre! Rassurez-vous, j’ai eu la même réaction que vous.
Sachez que le site social Twitter utilise Scala (en abandonnant Ruby).
Il faut préciser que Scala est un langage pur objet et en plus:

 * scala compilé produit du « bytecode » exécutable dans la JVM,
 * la syntaxe de Scala est proche de Java,
 * l’API java est supporté dans Scala,

Sachez qu'aucun prérequis n'est nécessaire (peut être faire l'exemple HelloWorld ici).

Le plan du billet est le suivant :

  • une introduction pour tenter d’expliquer l’utilité de Scala,
  • un premier exemple pour illustrer l’intérêt de Scala,
  • plusieurs démo sur les concepts de Scala.

Les démos sont réalisées sous Eclipse Helios avec installation du plugin scala (url update: http://download.scala-ide.org/releases/2.0.0-beta).
Sinon, on peut directement tester les morceaux de code scala sur le site http://www.simplyscala.com/.

Pour la suite, nous donnons:

  • un premier exemple, autre que le fameux HelloWorld qui, dans ce contexte n'apporte pas grand chose,
  • plusieurs démo sur les concepts de Scala.

Scala n’est pas un concurrent (direct) à Java. Scala concilie la programmation fonctionnelle et celle orientée objet (OOP).

L’orientée objet introduit, à juste titre, une couche d’abstraction utilisant à bon escient, j’ose espérer, les concepts de « design pattern »
afin de construire une solution maintenable et robuste.
Sauf que les contraintes des langages orientées objet font que des kilomètres de code utile (appelés aussi de la plomberie ) sont écrits
pour réaliser cette solution technique.
Scala concilie les deux approches en permettant, par exemple, de passer une nouvelle fonction en argument aux méthodes existantes.

Passons à la pratique..... c'est toujours mieux que les discours!

DEMO 1:

Après l’installation du plugin dans Eclipse, cliquer open new scala project ==> saisir le nom du projet « firstscalaproj» par exemple.
Vérifier que le JDK est de version 1.5 ou + puis ==> « next » ==> « finish »

Le projet créé avec les librairies de scala dans le « classpath» et un répertoire « src » vide pour l’instant.
Clic droit sur « src » ==> new package nommé « fr.netapsys.blog.exemple1 ».

Clic droit sur « src » ==> new « Scala Object » puis saisir le nom de la classe « FirstExemple » et saisir le nom du package ==> finish.
Une classe, par défaut publique, est créée dans le package avec, pour l'instant peu de lignes :

 /*scala*/
package fr.netapsys.blog.exemple1

object FirstExemple {
}

Nous la complétons pour ajouter l’équivalent de la méthode main de java comme suit :

 **scala**  FirstExemple.scala
1 package fr.netapsys.blog.exemple1
2 import System.out.println
 3 object FirstExemple {

 4   def main(args: Array[String]): Unit = {
	//function
 5	def afficheListe(liste: List[Int],msg:String) {
 6	  println("Affichage "+msg+" : "+liste)
	}
 7	val entiers = List(-1, 1, 2, 3, 4, 5, 6)
 8	afficheListe(entiers,"de la liste")

	/* filtre fonctionnel */
 9	val positifs = entiers.filter(_ > 0)
10	afficheListe(positifs,"des entiers positifs ")
	/* other filter fonctionnel */
11	val grands = entiers.filter(2<)  //_ > 2)
12	afficheListe(grands,"des entiers plus grands que 2 ")

	////un peu de fonctionnel ...interessant
13	val intermeds = positifs.filter(x => x > 1 && x < 6)
14	afficheListe(intermeds, "des entiers entre 2 et 5 ")

15	val exist=intermeds.exists(_==8)
16	if(exist) println("existe!")
17	else println ("n'existe pas!")
	//Enfin, une seconde façon d’afficher la liste
18	intermeds.foreach(println)		
19  }
20 }

Ecoutez, je sais bien ce que vous dites! On n’est loin de java et puis c’est assez … PERListe / Rubyiste.
Rassurez vous, nous décortiquons tout ce code pas à pas plus loin.

Mais avant, exécutons cette classe dans Eclipse par un clic droit sur « FirstExemple.scala » ==> Run as ==> Scala Application.

Le résultat de l'exécution est donné ci-dessous :
resultat_exec_ex1

Expliquons un peu :
Dans Scala et contrairement à java, une classe est par défaut publique. Un même fichier d'extension .scala peut contenir plusieurs classes.

Déclaration de classe (objet)

- Toute classe est publique donc pas de modificateur de visibilité
- Elle peut être abstraite comme en java. Scala va plus loin que java puisque même ses attributs peuvent être abstraits.
- On distingue une classe particulière nommé « object » utilisée dans ce démo. Elle reproduit le contexte statique de java. En scala l’objet est une instance singleton et donc ne nécessite pas d’être instanciée. Enfin, signalons qu’à la différence de java, le contexte statique n’existe pas.

Déclaration d’attributs

La syntaxe de déclaration d’un attribut est comme suit :
[indicateur de visibilité] (val|var) nom_attribut [:Type=Valeur]

Tout ce qui est entre crochets [] est optionnel.

L’indicateur de visibilité est optionnel peut prendre la valeur « private ou protected ». Quand rien n’est mentionné il est par défaut publique et donc accessible à l’extérieur de la classe.
Le symbole (var|val) indique qu’il peut être soit un attribut muable soit un immuable. Le choix est ici exclusif.
Notez que «val» est l’équivalent de « final » en java.

L’option [:Type] permet de préciser le type de l’attribut Int, String, Number, ..etc
Le système d’inférence de scala détermine le type d’un attribut au moment de l’affectation.
Par exemple,

 
private val nb:Int=9

var str:String

private var k:Int=_

val pStr=""

var abstrAttribut:Int

Donc, le champ nb est un objet Int initialisé à 9.
k est un Int initialisé avec la valeur par défaut (0 pour Int). Scala infère à pStr son type, ici String, à partir de la valeur d'init.

Enfin, le champ Int abstrAttribut est abstrait puisqu'il n'est pas initialisé.

Attention, si un champ n’est pas initialisé alors il est considéré comme abstrait. Scala étend le domaine « abstrait » et va plus loin que java.

Déclaration des constructeurs

Parlons des constructeurs de classes de scala qui sont légèrement (j’ai bien dit légèrement) différents de java mais pas de quoi nous décourager!

Le constructeur principal (et non le constructeur par défaut) se déclare en une seule ligne comme dans cet exemple :

class Entreprise(var raisonSociale :String,var id :Int)

Et c’est tout! Oui on a défini deux attributs de la classe et le constructeur qui prend en paramètres ces deux attributs. C'est concis.

Voilà, on peut instancier la classe comme suit :

Entrep :Entreprise=new Entreprise(“Pharamcie toto”,1)

Je crois que nous avons les éléments utiles pour détailler notre démo1.

object de notre démo1 n'a pas besoin de constructeur (c'est une instance reproduisant le contexte statique connu dans java).

La fonction/méthode def main est le point d'entrée (Ligne numérotée 4) et elle indique qu'elle prend en argument un tableau de String identique à java.
Elle retourne un type Unit et avec le signe "=" elle précise ce qu'elle doit retourner. Le type scala.Unit est l'équivalent de void en java.

Ligne 5, juste après avoir défini la fonction def afficheListe qui elle prend comme arguments une List et un String. Rien de nouveau sous le ciel scala! Oui, pour l'instant!
Ligne 7, on déclare un attribut List initialisée. L'inférence de scala détermine le type c'est à dire une liste Int. Ligne 8 affiche cette liste.

A Ligne 9 arrive aux "trucs" intéressants: On passe à la fonction filter de List une nouvelle fonction qui est : "_ > 0"

Ainsi, comme résultat du filtre on obtient les entiers positifs. Cette forme abrégée aurait pu être écrite sous la forme explicite: "x=>x>0"

Si vous êtes encore là, c'est que vous commencer à adopter scala.
Poursuivons, à la ligne 13 une autre fonction sous une forme plus élaborée
x=> x>2 && x=>x<6

qui permet de ne retenir que les entiers qui sont conformes aux deux conditions.
On obtient donc que les entiers compris (strictement) entre 2 et 6 comme la capture ci-dessus le confirme.

A la ligne 18, encore une autre façon de passer une fonction (ici System.out.println importée en haut) à la méhode foreach de List.

On peut aussi, passer le Logger de log4j ou toute autre méthode de trace comme suit :

val logger:Logger= Logger.getLogger(this.getClass().getName())

interms.foreach(logger.trace)

Ajouter log4j.jar au classpath du projet et, dans le code, la ligne

import org.apache.log4j.Logger.

Vous avez un aperçu de la richesse et la puissance de scala avec ces premiers exemples où l'emploi des filtres de scala. Ces filtres peuvent être adaptés et enrichis de manière simple.

En java c'était aussi possible (avec les classes anonymes bien qu'il y a des contraintes à respecter mais trop limité pour la récupération du binding contexte ). Mais, en java, le prix à payer est fort!
Peut-être que les closures dans les futures versions java (closures abandonnés dans java 7?) .

Dans les prochains billets nous détaillerons, entre autres, le code ci-après permettant de lire un fichier :

        var contenu=""
	val nomFichier="test.txt"
	try{
	 contenu = fromFile(nomFichier).mkString
	}catch{
	   case e:FileNotFoundException => e.getMessage()
	   logger.error("Fichier "+nomFichier)
	   System.exit(1)
	}	
        logger.info("contenu du fichier :
"+contenu)		

NOTE: En fait, une ligne suffit car le catch de l'exception est optionnel. En réalité, dans scala, Il n'y a pas de checked exception.
Pensez à l'import scala.io.Source.fromFile et java.io.FileNotFoundException.
Là il faut que je m'arrête! On reparlera de tout cela prochainement.

En attendant, enjoy!

NOTE: A la fin de la rédaction de cette première partie, j'ai découvert ce très bon article, en français, site que je conseille sa lecture.

Un commentaire

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.