Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
cnam:utc503:declarative:fonctionnelle [2023/11/06 19:33] – [1 - fonctions pures] jcheron | cnam:utc503:declarative:fonctionnelle [2023/11/10 07:27] (Version actuelle) – jcheron | ||
---|---|---|---|
Ligne 5: | Ligne 5: | ||
Basée sur l' | Basée sur l' | ||
- | La prog fonctionnelle n' | + | La prog fonctionnelle n' |
Les langages fonctionnels sont ceux vouent un culte à ces principes ou sont basés sur eux : | Les langages fonctionnels sont ceux vouent un culte à ces principes ou sont basés sur eux : | ||
Ligne 52: | Ligne 52: | ||
let pi = 3.14 ; | let pi = 3.14 ; | ||
const calculateArea = (radius) => radius * radius * pi; | const calculateArea = (radius) => radius * radius * pi; | ||
- | calculateArea(10);// | + | calculateArea(10);// |
</ | </ | ||
- | == Suppression de la variable globale | + | == Suppression de la variable globale |
<sxh javascript; | <sxh javascript; | ||
let pi = 3.14; | let pi = 3.14; | ||
Ligne 60: | Ligne 60: | ||
calculateArea(10, | calculateArea(10, | ||
</ | </ | ||
+ | == Ou (plus logique), passage de **pi** en constante : == | ||
+ | <sxh javascript; | ||
+ | const PI = 3.14; | ||
+ | const calculateArea = (radius) => radius * radius * PI; | ||
+ | calculateArea(10);// | ||
+ | </ | ||
+ | |||
+ | === b- Influence du contexte === | ||
+ | Exemples de fonctions impures : | ||
+ | == Lecture de fichiers : == | ||
+ | <sxh javascript; | ||
+ | const charactersCounter = (text) => `Character count: ${text.length}`; | ||
+ | |||
+ | function analyzeFile(filename) { | ||
+ | let fileContent = open(filename); | ||
+ | return charactersCounter(fileContent); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Génération d' | ||
+ | <sxh javascript; | ||
+ | function getRandomArbitrary(min, | ||
+ | return Math.random() * (max - min) + min; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === c- Mutabilité === | ||
+ | Exemple de fonction impure : | ||
+ | == Modification de globale : == | ||
+ | <sxh javascript; | ||
+ | let counter = 1; | ||
+ | function increaseCounter(value) { | ||
+ | counter = value + 1; | ||
+ | } | ||
+ | increaseCounter(counter); | ||
+ | console.log(counter);// | ||
+ | </ | ||
+ | |||
+ | Rendue pure : | ||
+ | |||
+ | <sxh javascript; | ||
+ | let counter = 1; | ||
+ | const increaseCounter = (value) => value + 1; | ||
+ | increaseCounter(counter);// | ||
+ | console.log(counter);// | ||
+ | </ | ||
+ | |||
+ | Avantages : | ||
+ | * Stabilité, prévisibilité | ||
+ | * Testabilité (unitaire) | ||
+ | * Réutilisation (sans effets de bord) | ||
+ | |||
+ | ==== 2- Immutabilité ==== | ||
+ | |||
+ | Les données doivent être immutables, c' | ||
+ | |||
+ | === Exemple d' | ||
+ | |||
+ | |||
+ | <sxh javascript; | ||
+ | let values = [1, 2, 3, 4, 5]; | ||
+ | let sumOfValues = 0; | ||
+ | for (let i = 0; i < values.length; | ||
+ | sumOfValues += values[i]; | ||
+ | } | ||
+ | sumOfValues // 15 | ||
+ | </ | ||
+ | |||
+ | === Version immutable obtenue par récursion : === | ||
+ | |||
+ | |||
+ | <sxh javascript; | ||
+ | let list = [1, 2, 3, 4, 5]; | ||
+ | let accumulator = 0; | ||
+ | function sum(list, accumulator) { | ||
+ | if (list.length == 0) { | ||
+ | return accumulator; | ||
+ | } | ||
+ | return sum(list.slice(1), | ||
+ | } | ||
+ | sum(list, accumulator); | ||
+ | list; // [1, 2, 3, 4, 5] | ||
+ | accumulator; | ||
+ | </ | ||
+ | |||
+ | === Avantages : === | ||
+ | |||
+ | |||
+ | * L' | ||
+ | |||
+ | ==== 3- Transparence référentielle ==== | ||
+ | |||
+ | Referential transparency | ||
+ | |||
+ | La transparence référentielle est obtenue grâce aux fonctions pures, et elle consiste à permettre le remplacement d'un appel d'une fonction pure, par la valeur qu' | ||
+ | |||
+ | **Exemple :** | ||
+ | |||
+ | Soit la fonction carré suivante : | ||
+ | <sxh javascript; | ||
+ | const square = (n) => n * n; | ||
+ | </ | ||
+ | |||
+ | Pour la même valeur en entrée, cette fonction pure retournera toujours la même valeur : | ||
+ | |||
+ | <sxh javascript; | ||
+ | square(2);// | ||
+ | square(2);// | ||
+ | square(2);// | ||
+ | // ... | ||
+ | </ | ||
+ | |||
+ | Avec le paramètre '' | ||
+ | |||
+ | <WRAP info> | ||
+ | '' | ||
+ | |||
+ | Grâce à ce concept, il est possible de memoïzer (https:// | ||
+ | </ | ||
+ | |||
+ | ==== 4- Fonction d' | ||
+ | |||
+ | Fonctions objet de première classe ou Functions as first-class entities : | ||
+ | |||
+ | Une fonction est un type de données (callback) et peut-être passée en paramètre d'une fonction ou être retournée par une fonction. | ||
+ | |||
+ | Les fonctions qui en manipulent d' | ||
+ | |||
+ | **Exemple :** | ||
+ | |||
+ | Considérons les fonctions suivantes : | ||
+ | |||
+ | <sxh javascript; | ||
+ | const doubleSum = (a, b) => (a + b) * 2; | ||
+ | const doubleSubtraction = (a, b) => (a - b) * 2; | ||
+ | </ | ||
+ | |||
+ | Nous pourrions considérer que nous avons 3 fonctions : | ||
+ | * somme | ||
+ | * soustraction | ||
+ | * double qui peut utiliser la soustraction, | ||
+ | |||
+ | <sxh javascript; | ||
+ | const | ||
+ | sum = (a, b) => a + b; | ||
+ | const subtraction = (a, b) => a - b; | ||
+ | const doubleOperator = (f, a, b) => f(a, b) * 2; | ||
+ | |||
+ | doubleOperator(sum, | ||
+ | doubleOperator(subtraction, | ||
+ | </ | ||
+ | |||
+ | **doubleOperator** est une fonction d' | ||
+ | |||
+ | ==== 5- Monades ==== | ||
+ | Structure permettant de manipuler des langages fonctionnels purs dans des traits impératifs. | ||
+ | **Exemples :** | ||
+ | * Result may or may not exist: solved by the Maybe monad. | ||
+ | * Nondeterministic number of result: solved by the List monad. | ||
+ | * Outside world interaction: | ||
+ | * Eventual result: solved by the Promise/ | ||
+ | * Dependence on state: solved by the State monad. | ||
+ | * Errors: solved by the Error monad. | ||
+ | ===== Applications ===== | ||
+ | * [[https:// | ||
+ | programming-with-js/ | ||