Ce document vise à présenter la programmation fonctionnelle sous Scala.
Les points abordés sont le paradigme fonctionnel, fonction anonyme, fonction d’ordre supérieur, Clôture, fonction partielle, la récursivité, Curryfication. Chaque notion est accompagnée par des exemples.
2. Contexte
Cette étude a été présentée dans le cadre
du séminaire « Data Science principes, outils
et applications » au laboratoire Cermsem.
datascience.km@gmail.comM. MICHRAFY 2
3. Plan
• Objectif
• Prérequis
• Tout est fonction
• Fonction pure
• Fonction anonyme
• Fonction d’ordre supérieur
• Clôture
• Fonction partielle
• Récursivité
• Curryfication
datascience.km@gmail.comM. MICHRAFY 3
4. Objectif
Cette étude vise à présenter la
programmation fonctionnelle sous Scala.
datascience.km@gmail.comM. MICHRAFY 4
6. Tout est fonction
• Dans le paradigme fonctionnel, tout est fonction.
• Un traitement complexe est composé de plusieurs
fonctions
datascience.km@gmail.comM. MICHRAFY 6
7. Fonction en scala
• En scala, une fonction est un objet qui peut être affecté à
une variable.
• La définition d’une fonction peut être effectuée n’importe
où dans un fichier source.
• La définition d’une fonction en scala nécessite l’utilisation
du mot clé def suivi du nom de la fonction, de zéro,
d’un ou de plusieurs arguments d’entrée, le type de
retour et le corps de la fonction
def add(x:Int, y:Int) : Int = {return x+y;}
Nom de la fonction
Arguments d’entrée
Valeur de retour
Corps de la fonction
datascience.km@gmail.comM. MICHRAFY 7
8. Appel à une fonction en scala
• L’appel d’une fonction se fait via son nom, suivi par les
arguments d’entrée entre parenthèses et séparés par un virgule.
• Si la fonction ne demande pas d’argument d’entrée, l’appel se
fait seulement avec son nom, et optionnellement suivi par une
paire de parenthèses vides ().
def add(x:Int, y:Int) : Int = {return x+y;}
Add(8,17) Appel de la fonction add
Définition de la fonction add
def hello() =
hello()
hello
Définition de la fonction hello
Appel de la fonction hello avec ()
Appel de la fonction hello sans ()
datascience.km@gmail.comM. MICHRAFY 8
9. Fonction pure
• Une fonction pure est une fonction qui respecte les 2
critères suivants :
1. La fonction est déterministe, c-à-d renvoie toujours la même
valeur pour les mêmes arguments
2. La fonction ne retourne que la valeur résultat, sans effet de bord.
• Les fonctions arithmétiques sont des fonctions pures
• Les fonctions mathématiques sont des fonctions pures
• Toute fonction à effet de bord n’est pas une fonction
pure
datascience.km@gmail.comM. MICHRAFY 9
10. Fonctions mathématiques
Fonction Sin def sin(x:Double) : Double = Math.sin(x)
Fonction
identité
def identite(x:Double) : Double = x
Fonction
constante
def constante(x:Double) : Double = 7
Fonction
affine
def affine(x:Double) : Double = 3*x+5
Formulation syntaxique en scala
Nom de la fonction
Argument d’entré et son type
Expression de retour
Type de retour
datascience.km@gmail.comM. MICHRAFY 10
12. Fonction anonyme : principe
• Une fonction anonyme en scala permet de définir une
fonction sans déclarer le nom de la fonction
• Une fonction anonyme est similaire à une lambda
expression et permet de créer des fonctions à la volée
• Une fonction anonyme peut être utilisée :
• pour initialiser une variable
• comme argument d’une fonction
• comme valeur de retour d’une fonction
datascience.km@gmail.comM. MICHRAFY 12
13. Fonction anonyme : syntaxe
• La syntaxe d’une fonction anonyme commence par une
liste d’arguments séparés par des virgules et entourés par
des parenthèses. Observons l’exemple suivant :
scala> val add = (x:Int, y:Int) => x+y
La fonction anonymeAdd est initialisé par la fonction anonyme
datascience.km@gmail.comM. MICHRAFY 13
14. Fonction anonyme : invocation
scala> val add = (x:Int, y:Int) => x+y
add: (Int, Int) => Int = <function2>
scala> add(7,8)
res4: Int = 15
Invocation de la fonction
anonyme
Définition de la fonction
anonyme
Comment les fonctions anonymes sont-elles créées ?
Pourquoi <fonction2>?
datascience.km@gmail.comM. MICHRAFY 14
15. Fonction anonyme : construction
scala> val add1:(Int, Int) => Int = (x:Int, y:Int) => x+y
add1: (Int, Int) => Int = <function2>= <function2>= <function2>= <function2>
scala> add1(1,10)
res0: Int = 11
scala> val add2: Function2[Function2[Function2[Function2[Int,Int,IntInt,Int,IntInt,Int,IntInt,Int,Int]]]] = ((((x:Intx:Intx:Intx:Int, y:Int) =>, y:Int) =>, y:Int) =>, y:Int) => x+yx+yx+yx+y
add2: (Int, Int) => Int = <function2><function2><function2><function2>
scala> add2.applyapplyapplyapply(1,10)
res1: Int = 11
• Une fonction anonyme est instanciée par un objet de type « fonction »
• L’objet étend le type FonctionNFonctionNFonctionNFonctionN, N désignant l’arité de la fonction anonymes
• L ’objet FonctionN dispose d’une méthode « apply »
datascience.km@gmail.comM. MICHRAFY 15
16. Fonction comme variable
• En scala et dans le paradigme fonctionnel en général,
nous pouvons utiliser une fonction comme variable.
scala> val valImpair = (n:Int) => 2*n + 1
valImpair: Int => Int = <function1>
scala> valImpair(10)
res3: Int = 21
La variable valImpair a pour valeur la fonction <function1>
datascience.km@gmail.comM. MICHRAFY 16
17. Fonction comme argument : déclaration
• Il est aussi possible de définir une fonction qui prend en
entrée une fonction
• Ce principe est similaire au pointeur de fonction en
C/C++ ou aux interfaces fonctionnelles en Java
• Il suffit de déclarer la signature de la fonction
defdefdefdef nomFonctionnomFonctionnomFonctionnomFonction(fctfctfctfct:([:([:([:([paramsparamsparamsparams]) =>]) =>]) =>]) => typeRetourtypeRetourtypeRetourtypeRetour, arg:type, ...) : typeRetourtypeRetourtypeRetourtypeRetour = {....}
Fonction comme argument d’une autre fonction
datascience.km@gmail.comM. MICHRAFY 17
18. Fonction comme argument : exemple
scala>scala>scala>scala> def operationoperationoperationoperation(op:(op:(op:(op:(Int,IntInt,IntInt,IntInt,Int)=>Int)=>Int)=>Int)=>Int, x:Int,y:Int) : Int = op(x,y)
operation: (op: (Int, Int) => Int, x: Int, y: Int)Int
scala>scala>scala>scala> def addaddaddadd(x:Int,y:Int):Int = x+y
add: (x: Int, y: Int)Int
scala>scala>scala>scala> def produitproduitproduitproduit(x:Int, y:Int):Int = x*y
produit: (x: Int, y: Int)Int
scala>scala>scala>scala> operationoperationoperationoperation(addaddaddadd,7,8)
res4: Int = 15
scala>scala>scala>scala> operationoperationoperationoperation(produit,produit,produit,produit,7,8)
res5: Int = 56
operation a la fonction op
comme argument
Les fonctions add et produit
ont la même signature que op
Appel de la fonction operation avec add
comme paramètre
Appel à la fonction operation avec produit
comme paramètre
datascience.km@gmail.comM. MICHRAFY 18
19. Fonction comme valeur de retour
• Il est aussi possible d’avoir une fonction comme valeur de
retour d’une fonction
• Dans ce cas, la fonction doit avoir une valeur de retour
de type fonction ou une fonction anonyme
• Il préférable d’utiliser les accolades pour la lisibilité.
datascience.km@gmail.comM. MICHRAFY 19
20. Fonction comme valeur de retour
scala>scala>scala>scala> def fabriqueFctAffinefabriqueFctAffinefabriqueFctAffinefabriqueFctAffine(a:Int ,b:Int) : (Int)=>Int
| = {(x:Int)=> a*x+b}
fabriqueFctAffine: (a: Int, b: Int)Int => Int
scalascalascalascala> def diag = fabriqueFctAffinefabriqueFctAffinefabriqueFctAffinefabriqueFctAffine(2,3)
diag: Int => Int
scalascalascalascala> diag(1)
res0: Int = 5
datascience.km@gmail.comM. MICHRAFY 20
La fonction fabriqueFctAffine renvoie une fonction affine ayant
pour coefficients les arguments a et b fournis en entrée
diag est la fonction définit par : → → 2 3
Signature de la fonction
fabriqueFctAffine
Signature de la fonction diag
21. La fonction composée
• La fonction composée (notée o en mathématique) est la
fonction qui prend en entrée deux fonctions et retourne la
fonction composée des deux
• Soient deux fonctions F et G, pour définir FoG, il est
nécessaire que l’ensemble {G(x), x dans Domaine(G)}
inclut dans Domaine(F) :
∶ 1 → 2, ∶ 2 → 2
∶ 1 ∁ 2
datascience.km@gmail.comM. MICHRAFY 21
22. La fonction composée
datascience.km@gmail.comM. MICHRAFY 22
F(x) = x*x
G(x) = x+1
FoG(x) = F(G(x))
= F(x + 1) = x*x+1
Formulation mathématique
Opérateur o
scala>scala>scala>scala> def FFFF(x : Int) : Int = x*x
F: (x: Int)Int
scala>scala>scala>scala> def GGGG(x : Int) : Int = x + 1
G: (x: Int)Int
scala>scala>scala>scala> defdefdefdef compose(Fcompose(Fcompose(Fcompose(F:(Int)=>(Int), G:(Int)=>(Int)) : (Int)=>(Int) = (Int)=>F(G(Int))
compose: (F: Int => Int, G: Int => Int)Int => Intcompose: (F: Int => Int, G: Int => Int)Int => Intcompose: (F: Int => Int, G: Int => Int)Int => Intcompose: (F: Int => Int, G: Int => Int)Int => Int
Compose(F,G) = FoG
23. Clôture : principe
• Une clôture ou fermeture est une fonction dont la valeur
de retour dépend de la valeur d'une ou plusieurs variables
déclarées à l'extérieur de cette fonction
• Les clôtures permettent d’encapsuler une partie du
contexte d’exécution dans une fonction
datascience.km@gmail.comM. MICHRAFY 23
24. Clôture : exemple
scala> val a = 2
a: Int = 2
scala> val b = 3
b: Int = 3
scala> def affine(x:Int,y:Int):Int = aaaa*x + bbbb
affine: (x: Int, y: Int)Int
scala> affine(1,1)
res7: Int = 5
a, b sont déclarées en dehors de la portée
de la fonction affine
datascience.km@gmail.comM. MICHRAFY 24
25. Fonction partielle
• En figeant les valeurs d’un sous-ensemble des
paramètres d’une fonction connue, on obtient une
fonction partielle (projection, spécialisation)
scala>scala>scala>scala> def produit(x:Int, y:Int):Int = x*y
produit: (x: Int, y: Int)Int
scala>scala>scala>scala> val partialyProduit = produit(2,_:Int)produit(2,_:Int)produit(2,_:Int)produit(2,_:Int)
partialyProduit: Int => Int = <function1<function1<function1<function1>>>>
scala>scala>scala>scala> partialyProduit(7)
res10: Int = 14
datascience.km@gmail.comM. MICHRAFY 25
26. Fonction récursive
• Une fonction récursive est une fonction qui peut s’appeler
elle-même.
• La récursivité reproduit le formalisme de la relation de
récurrence en mathématique
• La récursivité doit satisfaire deux conditions :
• Un ou plusieurs cas d’arrêts qui ne font pas appel à la fonction
• Définir le cas général en fonction des états antérieurs
• La récursivité est un principe fondamental en
programmation fonctionnelle, permettant de remplacer les
boucles.
datascience.km@gmail.comM. MICHRAFY 26
27. Fonction récursive : intérêt
• Pour des structures de données récursives, il est bien
plus facile d'écrire des algorithmes récursifs qu'itératifs
• Certains algorithmes sont extrêmement difficiles à écrire
dans un style itératif
• Dans certains cas, les fonctions récursives permettent
d’écrire des programmes très lisibles, et aussi de
concevoir des algorithmes dont l'analyse ou la preuve
sera facilitée.
datascience.km@gmail.comM. MICHRAFY 27
28. Fonction récursive : Calcul PGCD
datascience.km@gmail.comM. MICHRAFY 28
a = kb + r et 0 ≤ r < b
a si b=0
PGCD(b,r)
PGDC(a,b)=
Algorithme d’Euclide
appel à PGCD(42,24)
. Appel a PGCD(24,18)
.. Appel à PGCD(18,6)
…Appel à PGCD(6,0)
….retour 6
scalascalascalascala>>>> defdefdefdef pgcdpgcdpgcdpgcd((((a:Int,b:Inta:Int,b:Inta:Int,b:Inta:Int,b:Int) :) :) :) : IntIntIntInt ={={={={
|||| if(bif(bif(bif(b==0) a==0) a==0) a==0) a
|||| elseelseelseelse pgcdpgcdpgcdpgcd((((b,b%ab,b%ab,b%ab,b%a))))
| }| }| }| }
pgcd: (a: Int, b: Int)Int
scalascalascalascala> pgcd(42,24)
res0: Int = 6
29. Fonction récursive : pile d’exécution
• Chaque appel d’une fonction récursive est associé à un
contexte d’exécution propre
• Ce contexte d’exécution est composé de :
• l'adresse mémoire de l'instruction qui a appelé la fonction
• les valeurs des paramètres et des variables définies par la fonction
• La récursivité implique une allocation dynamique de la
mémoire.
• La pile d’exécution fonctionne selon le principe LIFO
• La pile ayant une taille fixe, une mauvaise utilisation de la
récursivité peut entraîner son débordement.
datascience.km@gmail.comM. MICHRAFY 29
30. Fonction récursive : pile d’exécution
appel à fact(4)
. 4*fact(3) = ?
. appel à fact(3)
. . 3*fact(2) = ?
. . appel à fact(2)
. . . 2*fact(1) = ?
. . . appel à fact(1)
. . . . 1*fact(0) = ?
. . . . appel à fact(0)
. . . . retour de la valeur 1
. . . . 1*1
. . . retour de la valeur 1
. . . 2*1
. . retour de la valeur 2
. . 3*2
. retour de la valeur 6
. 4*6
retour de la valeur 24
scalascalascalascala>>>> def fact(n : Int) : Int
| = if(n==0) 1 else n*fact(n-1)
fact: (n: Int)Int
scalascalascalascala>>>> fact(4)
res2: Int = 24
1 si n=0
n*fact(n-1)fact(n)=
datascience.km@gmail.comM. MICHRAFY 30
31. La récursivité : terminale ou non ?
Deux types
Terminale Non Terminale
datascience.km@gmail.comM. MICHRAFY 31
• Une fonction f est récursive terminale, si tous les appels récursifs invoquent f au
plus une fois et sont de la forme return f(…)
• Une fonction récursive terminale a un coût en mémoire constant (pas
d’empilement des appels récursifs).
• Il est toujours possible de transformer une fonction récursive non terminale en une
fonction terminale en introduisant des accumulateurs comme arguments
d’entrée
32. Récursivité : Transformation
def factNonTerminalfactNonTerminalfactNonTerminalfactNonTerminal(n:Int):Int ={
if(n==0) 1
else n+factNonTerminalfactNonTerminalfactNonTerminalfactNonTerminal(n-1)
}
datascience.km@gmail.comM. MICHRAFY 32
def factTerminalfactTerminalfactTerminalfactTerminal(n:Int, m:Int) : Int ={
if(n==0) m
else factTerminalfactTerminalfactTerminalfactTerminal(n-1,m*n)
}
Transformation Terminale
Fonction récursive
non terminale
Fonction récursive
terminale
accumulateur
33. Récursivité : fonctions enveloppe et
auxiliaire
• Une fonction enveloppe est une fonction qui encapsule
une fonction ou plusieurs (nommée fonction enveloppée ou
auxiliaire).
• Les fonctions enveloppes peuvent être utilisées pour
initialiser les arguments d’une fonction récursive terminale
• La réécriture d’une fonction en récursivité terminale
nécessite l’introduction d’un argument ou plusieurs et dont
l’initialisation dépend de l’implémentation. La solution
consiste à implémenter une fonction récursive terminale
comme une fonction auxiliaire d’une fonction principale
datascience.km@gmail.comM. MICHRAFY 33
34. Récursivité : réécriture d’une fonction
def factNonTerminalfactNonTerminalfactNonTerminalfactNonTerminal(n:Int):Int ={
if(n==0) 1
else n+factNonTerminalfactNonTerminalfactNonTerminalfactNonTerminal(n-1)
}
datascience.km@gmail.comM. MICHRAFY 34
def factTerminalfactTerminalfactTerminalfactTerminal(n:Int, m:Int) : Int ={
if(n==0) m
else factTerminalfactTerminalfactTerminalfactTerminal(n-1,m*n)
}
Transformation Terminale
def factfactfactfact(n : Int) : Int = {
def factTerminalfactTerminalfactTerminalfactTerminal(n:Int, m:Int) : Int ={
if(n==0) m
else factTerminalfactTerminalfactTerminalfactTerminal(n-1,m*n)
}
factTerminalfactTerminalfactTerminalfactTerminal(n,1(n,1(n,1(n,1))))
}
Réécriture de la fonction
Définition de la fonction auxiliaire
1
2
Appel à la fonction auxiliaire avec deux
arguments dont un est initialisé à 1
35. Récursivité : Primalité d’un nombre
• Un nombre p est premier s’il admet que deux diviseurs 1
et n
• Tout nombre pair est non premier à l’exception de 2
• Pour améliorer les performance, il suffit de tester
seulement les nombre entre 2 et √ .
• Comme un nombre premier est toujours impair – à
l’exception de 2- il suffit de tester les nombre impairs
entre 3 et √ .Mais ceci est utile pour un algorithme itératif
datascience.km@gmail.comM. MICHRAFY 35
36. Récursivité : Primalité d’un nombre
def isPrimAuxisPrimAuxisPrimAuxisPrimAux((((p:Intp:Intp:Intp:Int, d:Int), d:Int), d:Int), d:Int) : Boolean={
if(d*d <= p){
if(p%d==0) false
else isPrimAux(p,d+1);
}
else true
}
def isPrimisPrimisPrimisPrim((((p:Intp:Intp:Intp:Int)))) : Boolean ={
def isPrimAux(p:Int, d:Int):Boolean ={
if(d*d <= p){
if(p%d==0) false
else isPrimAux(p,d+1);
}
else true
}
isPrimAux(p,2)
}
d=2
isPrim(p) =
si d*d <= p
si d/p alors faux
sinon estPrim(p,d+1)
sinon vrai
Algorithme pour tester la primalité
1
2
datascience.km@gmail.comM. MICHRAFY 36
37. Récursivité: fonction d’ordre sup.
• n et m deux entiers, n < m
• Calculer A et B :
- ∑ - ∑
datascience.km@gmail.comM. MICHRAFY 37
Similarité : la somme
!: →
!
#: →
#
$ !% & , $ #
Réécriture de A et B
Ecrire une fonction sum qui prend en
entrée une fonction f
Idée
'() !, , )
0 ' + )
! '() !, 1, ) '
Relation de
récurrence.
38. Récursivité: fonction d’ordre sup.
• n et m deux entiers, n < m
• Calculer A et B :
- ∑ - ∑
datascience.km@gmail.comM. MICHRAFY 38
!: →
!
#: →
#
$ !% & , $ #
'() !, , )
0 ' + )
! '() !, 1, ) '
def sumsumsumsum(ffff: Int => Int, a: Int, b: Int): Int ={
if (a > b) 0 else f(a) + sum(f, a + 1, b)
}
val A = sum(x=>x)
val B = sum(x=>x*x)
def sumCompactesumCompactesumCompactesumCompacte(f: Int => Int): (Int, Int) => Int = {
def sum(a: Int, b: Int): Int =if (a > b) 0 else f(a) + sum (a + 1, b)
sum
}
Calcul de A et B
39. Récursivité : stratégie d’implémentation
• Un algorithme récursif peut donner lieu à plusieurs
implémentations.
• Ce cas se présente lorsque le problème est composé de
plusieurs sous-problèmes de même nature. Ceci est similaire
au principe de diviser pour régner ou aux algorithmes relevant
de la programmation dynamique.
• L’implémentation dépend à la fois de la :
• La Stratégie du parcours ou de construction
• L’initialisation des paramètres
• Une mauvaise implémentation peut pénaliser le temps de
calcul.
Analysons la suite de Fibonacci
datascience.km@gmail.comM. MICHRAFY 39
40. Récursivité : Fibonacci, version naïve
Fibonacci(n)=
0 si n = 0
1 si n =1
Fibonacci(n-1) + Fibonacci(n-2)
Suite de fibonacci
def fibonaccifibonaccifibonaccifibonacci(n:Int) : Int = {
if(n < 2) n
else fibonaccifibonaccifibonaccifibonacci(n-1) + fibonaccifibonaccifibonaccifibonacci(n-2)
}
datascience.km@gmail.comM. MICHRAFY 40
41. Récursivité : analyse de l’algorithme
Fibonacci 7
6 5
4 35 4
4 3 3 2 3 2 2 1
1 03 2 2 1 2 1 2 1 1 0
1 01 01 01 02 1
1 0
1 0
• Chaque nœud désigne un terme de la suite de fibonacci
• Les nœuds -portant les valeurs 2 à 7- sont des appels récursifs
• Les nœuds verts désignent les termes 0 et 1 de la suite fibonacci
• On constate le calcul redondant généré par l’algorithme « naïf »de fibonacci.
Arborescence de
Fibonacci(7)
7
0
datascience.km@gmail.comM. MICHRAFY 41
42. Récursivité : algorithme constructif de
fibonacci
• Le problème consiste à ne pas recalculer le même terme
de fibonnaci plusieurs fois.
• Remarquons que le terme n de Fibonacci nécessite le
calcul des termes de n-1 à 0.
• Par conséquent, pour éviter le calcul redondant, nous
pouvons calculer le terme n en commençant par calculer
le terme 0,1, 2 …. via la relation de récurrence.
• Pour calculer le terme n sans redondance, il faut
mémoriser les termes n-1 et n-2.
• Nous avons besoin aussi d’un test d’arrêt, ce qui est le
terme n.
datascience.km@gmail.comM. MICHRAFY 42
43. Récursivité : Fibonacci, algorithme constructif
p, a1,a0 trois entiers
Fibonacci(n,p,a1,a0) =
n si n<2
Fibonacci(n,p+1,a1+a0,a1) si p<n
a1+ a0 sinon
a0 = 0, a1=1 ( a0 et a1 2 termes consécutifs de fibonacci)
p=2, ( p varie de 2 à n)
Relation de
récursivité
Etape
d’initialisation
• C’est un algorithme constructif.
• A chaque étape, l’algorithme conserve les deux états m-1, m-2
• Les deux états consécutifs sont stockés dans a0 et a1
• Les termes 0 et 1 sont utilisés dans la phase d’initialisation
• Le terme n de Fibonacci est la somme de a0 et a1
datascience.km@gmail.comM. MICHRAFY 43
44. Récursivité : Fibonacci, algorithme constructif
p, a1,a0 trois entiers
Fibonacci(n,p,a1,a0) =
n si n<2
Fibonacci(n,p+1,a1+a0,a1) si p<n
a1+ a0 sinon
2
10
3
1
4
2
5
3
4
65
7
n=7, p=2, a0=0, a1=1
def fibonaccifibonaccifibonaccifibonacci(n:Int):Int={
def fibfibfibfib(n:Int, p:Int, a0:Int, a1:Int) : Int ={
if(n<2) n
else{
if(p<n) fibfibfibfib(n, p+1, a1+a0,a1)
else a1+a0
}
}
fib(n,2,1,0)
}
Plus de calcul
redondant
0
7
Chaque ligne
désigne les termes
consécutifs
datascience.km@gmail.comM. MICHRAFY 44
45. Curryfication : principe
• La curryfication désigne l'opération transforme une
fonction à plusieurs arguments à une fonction à un
argument qui retourne une fonction prenant le reste des
arguments. Elle permet de convertir une fonction avec
plusieurs paramètres en créant une chaîne de fonction,
chacun attendant un seul argument.
• En mathématique, on peut définir une fonction à plusieurs
variables alors que le Lambda-calcul se limite à des
fonctions avec une seule variable. Une correspondance
« curryfication » bijective a été définie entre les fonctions
Lambda-calcul et les fonctions multivariées
datascience.km@gmail.comM. MICHRAFY 45
46. Curryfication : Transformation
• A chaque fonction multivariées, on associe une fonction avec
une seule variable. La curryfication s’appuie sur les définition
des fonctions partielles
, →
, - → -
!. ∶ → →
→ !. - -
Curryfication
! ∶ →
, -, / → - /
!.: 0 → →
-, / → - /
!.,1 ∶ → % → &
/ → - /
→ !.
- → !.,1
Fonctions de
curryfication
→ !.
2
1
datascience.km@gmail.comM. MICHRAFY 46
47. Curryfication : méthode add
scala> def add1add1add1add1(x:Double, y:Double):Double = x + y
add1add1add1add1: (x: Double, y: Double)Double
scala> def add1Curry = (x : Double) => (y : Double) => x + y
add1Curry: Double => (Double => Double)
scala> def add2add2add2add2(x:Int,y:Int,z:Int) : Int = x+y+z
add2: (x: Int, y: Int, z: Int)Int
scala> def add2Curryadd2Curryadd2Curryadd2Curry(x:Int) : Int => (Int => Int) = y => (z => x + y + z)
add2Curryadd2Curryadd2Curryadd2Curry: (x: Int)Int => (Int => Int)
Curryfication
Curryfication
datascience.km@gmail.comM. MICHRAFY 47
48. Références bibliographiques
• Beginning Scala, par David Pollak, 2015
• Programming in Scala, par Martin Odersky and al., 2011
• Programming Scala, par Dean Wampler, Alex Payne, 2014
• Functional Thinking par Neal Ford, 2014
• Functional Programming in Scala, par Paul Chiusano,
Rúnar Bjarnason, 2014
datascience.km@gmail.comM. MICHRAFY