Cette page résume le cours de programmation fonctionnelle
scala> val liste = List (99, 42, 34, 65)
liste : List[Int] = List (99, 42, 34, 65)
scala> liste(2)
res0: Int = 34
scala> liste.head
res1: Int = 99
scala> liste.tail
res2: List[Int] = List(42, 34, 65)
scala> 14 :: 45 :: 21 :: Nil
res3: List[Int] = List (14, 45, 21)
scala> val paire = (99, " luftballon ")
paire: (Int , String ) = (99 , luftballon )
scala> paire._1
res0: Int = 99
scala> paire._2
res1: String = luftballon
scala> val triplet = (4, 2, 1)
Triplet : (Int, Int, Int) = (4, 2, 1)
def max(x: Int , y: Int) : Int = {
if (x > y) x
else y
}
OU
def max(x: Int , y: Int) = if (x > y) x else y
Il est possible d'ajouter des fonctions en paramètre :
def somme(f: Int => Int, a: Int, b: Int) : Int =
if (a > b ) 0
else f(a) + somme(f, a+1, b)
class Rationnel (n: Int , d: Int){
// Fonction privée
private def pgcd(a: Int , b: Int): Int = if (b == 0) a else pgcd(b, a % b)
// Variable de classe
val numer = n/( pgcd(n,d) abs)
val denom = d/( pgcd(n,d) abs)
// Override de fonction
override def toString = s"$numer/$denom"
// Fonction publique
def plus(autre: Rationnel ) =
new Rationnel (numer*autre.denom + autre. numer *denom , denom*autre.denom)
// Override de calcul
def +(autre: Rationnel ) =
new Rationnel (numer*autre.denom + autre.numer*denom , denom*autre.denom)
def unary_- = new Rationnel (-numer , denom )
def -(autre : Rationnel ) = this + -autre
}
object Rationnel {
// Sert souvent de factory
def apply(n: Int , d: Int) =if(d<0) new Rationnel (-n,-d) else new Rationnel (n,d)
implicit def int2Rationnel (n: Int) : Rationnel = new Rationnel (n, 1)
}
Si un objet a le même nom qu'une classe, alors l'objet et la classe sont compagnons. La classe a accès aux valeurs de l'objet.
def polynome2(a: Double, b: Double, c: Double)(x: Double) : Double =
a*x*x + b* x + c
scala> val monPoly = polynome2(5, -3.1, 1)_
monPoly: Double => Double = <function>
scala> monPoly(10)
res0: Double = 470.0
scala> val monPoly2 : Double => Double = polynome2(-2,5, 7)
monPoly2: Double => Double = <function>
scala> monPoly2(2)
res1: Double = 9.0
scala>polynome2(5, -2, 3)(3)
res2: Double = 42.0
La récursion terminale est possible si le dernier appel exécuté dans une fonction est
def est_present(x: Int, l : List[Int]) : Boolean =
if( l.isEmpty ) false
else if(l.head == x) true
else est_present(x, l.tail)
Version améliorée d'un switch : Adéquation à un motif.
x match {
case 1 => "un"
case Deux => "deux"
case `trois` => "trois"
case _ => "inconnu"
}
liste match {
case Nil => "Liste vide"
case 1 :: Nil => "Liste contenant 1, et rien d’autre"
case _ :: Nil => "Liste avec un seul élément"
case 1 :: 2 :: Nil => "Liste contenant 1, 2 et rien d’autre"
case x :: xs => s"Liste avec $x en tête, suivant de la liste $xs"
}
for { i <- 2 until n
j <- 1 until i
if estPremier( i+j)
} yield (i, j)
Conteneur avec 0 ou 1 élément
scala> val optInt = Some(42)
optInt : Option[Int] = Some(42)
scala> val optString = Some("Hello")
optString : Option[String] = Some(Hello)
scala> val lecture = Option(scala.io.StdIn.readLine())
lecture: Option[String] = None
scala> val tryInt = Success(42)
tryInt : Try[Int] = Success(42)
scala> val tryString = Success("Hello")
tryString : Try[String] = Success(Hello)
scala> val div = Try( 100/ 0)
div: Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
scala> val resultat : Try[String] = Failure(new Exception("erreur"))
resultat : Try[String] = Failure(java.lang.exception : erreur)
def divisionLente(x: Int, y: Int) = {Thread.sleep(5000); x/y }
scala> val resultat = Future{ divisionLente(4, 2) } // retourne un résultat immédiat
resultat : scala.concurent.Future[Int] = scala.concurent…
val resultatDéfinitif = Await.result(resultat) // bloque pour 5 sec.
scala> List(0, 1, 2, 3).zip( List("a", "b", "c", "d") )
res0: List[(Int, String)] = List((0, a), (1, b), (2, c), (3, d) )
scala> List((0, "a"), (1, "b"), (2, "c"), (3, "d")).unzip
res0: (List[Int], List[String]) =(List(0, 1, 2, 3), List(a, b, c, d))
mkstring - Transforme une liste en chaîne de caractères
scala> List(0, 1, 2, 3, 4, 5).map(x=> x*x)
res0: List[Int] = List(0, 1, 4, 9, 16, 25)
scala> List("pommes", "oranges", "poires").flatMap( _.toList )
res1: List[Char] = List(p, o, m, m, e, s, o, r, a, n, g, e, s, p, o, i, r, e, s)
scala> List(0, 1, 2, 3, 4, 5).filter( _%2==0)
res0: List[Int] = List(0, 2, 4)
scala> List(0, 1, 2, 3, 4, 5).exists( _%2==0)
res0: Boolean = true
scala> List(0, 1, 2, 3, 4, 5).forall( _%2==0)
res0: Boolean = false
scala> List(1, 2, 3, 4).reduce( (x,y) => x+y )
res0: Int = 10
reduceLeft - reduce qui va de la gauche vers la droite
reduceRight - reduce qui va de la droite vers la gauche
foldLeft - Réduit une collection à une valeur de type différent de la liste
scala> def op(p: (Int, Int), x: Int) = {
| if (x < p._1) (x, p._2)
| else if (p._2 < x) (p._1, x)
| else p }
op: (p: (Int, Int), x: Int)(Int, Int)
scala> List(3, 1, 4, 2).foldLeft( (3, 3) )(op)
res0: (Int, Int) = (1, 4)