Mais cela va bientôt changer. De plus en plus de concepts FP sont intégrés dans des langages tels que Java et Python . Et des langages plus modernes comme Haskell sont entièrement fonctionnels. Pour mettre la programmation fonctionnelle en termes simples
, alors c'est la création de fonctions pour travailler avec des variables immuables. En revanche, la programmation orientée objet consiste à utiliser un ensemble relativement constant de fonctions et que le programmeur est principalement occupé à modifier des variables existantes et à en créer de nouvelles.
La FP, de par sa nature, convient à la résolution de problèmes urgents, tels que l'analyse de données et l'apprentissage automatique . Cela ne signifie pas que vous devez dire adieu à la programmation orientée objet et passer complètement à la programmation fonctionnelle. Il est simplement utile pour le programmeur moderne de connaître les principes de base de la PF, ce qui lui permettra d'appliquer ces principes là où ils peuvent bien le servir.
La programmation fonctionnelle consiste à éliminer les effets secondaires
Afin de comprendre les principes de la programmation fonctionnelle, vous devez d'abord comprendre ce qu'est une «fonction». Cela peut paraître ennuyeux, mais au final, cela vous permettra de voir ce qui à première vue est imperceptible. Parlons donc des fonctions.
Une fonction, en termes simples, est une entité qui convertit certaines entrées qui lui sont passées en données de sortie qu'elle renvoie au lieu de l'appel. Certes, en fait, tout n'a pas toujours l'air aussi simple. Jetez un œil à la fonction Python suivante:
def square(x):
return x*x
Cette fonction est extrêmement simple. Il prend un argument,
x
qui est probablement de type int
, et peut-être de type float
ou double
, et renvoie le résultat de la mise au x
carré.
Et voici une autre fonction:
global_list = []
def append_to_list(x):
global_list.append(x)
À première vue, il semble qu'il accepte
x
un type et ne renvoie rien, car il ne contient aucune expression return
. Mais ne sautons pas aux conclusions!
La fonction ne pourra pas fonctionner normalement si la variable n'est pas déclarée à l'avance
global_list
. Le résultat de cette fonction est une liste modifiée stockée dans global_list
. Même si elle n'est global_list
pas déclarée comme une valeur transmise à l'entrée d'une fonction, cette variable change après l'appel de la fonction.
append_to_list(1)
append_to_list(2)
global_list
Après quelques appels à la fonction de l'exemple précédent, il n'y
global_list
aura plus de liste vide, mais une liste [1,2]
. Cela nous permet de dire que la liste, en fait, est la valeur fournie à l'entrée de la fonction, bien que cela ne soit en aucun cas fixé lorsque la fonction est déclarée. Cela peut être un problème.
Malhonnêteté lors de la déclaration de fonctions
Ces valeurs implicites d'entrée ou de sortie ont un nom officiel: effets secondaires. Nous utilisons ici des exemples très simples, mais dans des programmes plus complexes, les effets secondaires peuvent entraîner de réelles complications .
Pensez à la façon dont vous testeriez la fonction
append_to_list
. Il ne suffira pas de lire la première ligne de sa déclaration, et de découvrir qu'elle doit être testée en lui passant une valeur x
. Au lieu de cela, vous devrez lire l'intégralité du code de la fonction, déterminer ce qui s'y passe exactement, déclarer une variable global_list
, puis tester la fonction. Ce qui, dans notre exemple simple, ne semble pas poser de difficultés particulières, dans les programmes composés de milliers de lignes de code, sera complètement différent.
Heureusement, le problème ci-dessus est facile à résoudre. Vous devez juste être honnête lorsque vous spécifiez ce qui doit exactement aller à l'entrée de la fonction. La prochaine version de notre fonction est bien meilleure que la précédente:
newlist = []
def append_to_list2(x, some_list):
some_list.append(x)
append_to_list2(1,newlist)
append_to_list2(2,newlist)
newlist
Nous n'avons pas beaucoup changé dans ce code. En conséquence, la fonction in
newlist
, comme avant in global_list
, s'avère [1,2]
, et tout le reste a le même aspect qu'avant.
Cependant, nous avons apporté une modification importante à ce code. Nous nous sommes débarrassés des effets secondaires. Et c'est très bien.
À savoir, maintenant, après avoir lu la première ligne de la déclaration de fonction, nous savons exactement avec quelles données d'entrée elle fonctionne. En conséquence, si le programme ne se comporte pas comme prévu, il est facile de tester chaque fonction qu'il contient et de trouver celle qui ne fonctionne pas correctement. Les fonctions pures sont plus faciles à entretenir.
La programmation fonctionnelle consiste à écrire des fonctions pures
Une fonction qui, une fois déclarée, indique clairement ce qu'elle prend et ce qu'elle renvoie, est une fonction sans effets secondaires. Une fonction sans effets secondaires est une fonction pure.
Voici une définition très simple de la programmation fonctionnelle. Il s'agit d'écrire des programmes composés uniquement de fonctions pures. Les fonctions pures ne modifient jamais les données qui leur sont transmises, elles en créent simplement de nouvelles et les renvoient. (Notez que j'ai un peu triché dans l'exemple précédent. Il est écrit dans l'esprit de la programmation fonctionnelle, mais dans celui-ci, la fonction modifie la liste de variables globale. Mais ici, nous n'examinons que les principes de base de FP, c'est pourquoi je l'ai fait. Si vous voulez, ici vous pouvez trouver des exemples plus stricts de fonctions pures.)
De plus, lorsque vous travaillez avec des fonctions pures, vous pouvez vous attendre à ce qu'elles, recevant les mêmes données en entrée, génèrent toujours la même sortie. Et les fonctions qui ne sont pas pures peuvent dépendre de certaines sortes de variables globales. En conséquence, ils, recevant la même entrée, peuvent produire des résultats différents, en fonction de la valeur des variables globales. Ce fait peut considérablement compliquer le débogage et la maintenance du code.
Il existe une règle empirique simple pour détecter les effets secondaires. Puisque lors de la déclaration de fonctions pures, il faut clairement définir ce qu'elles reçoivent en entrée et en retour, les fonctions qui n'acceptent ou ne renvoient rien ne seront pas propres. Si vous décidez d'incorporer des techniques de programmation fonctionnelle dans votre projet, la première chose que vous voudrez probablement faire est de vérifier vos déclarations de fonctions.
Ce que la programmation fonctionnelle n'est pas
▍ Cartographier et réduire les fonctions
Les boucles sont des mécanismes qui n'ont rien à voir avec la programmation fonctionnelle. Jetez un œil aux boucles Python suivantes:
integers = [1,2,3,4,5,6]
odd_ints = []
squared_odds = []
total = 0
for i in integers:
if i%2 ==1
odd_ints.append(i)
for i in odd_ints:
squared_odds.append(i*i)
for i in squared_odds:
total += i
Avec l'aide de ce code, nous résolvons des problèmes simples, mais cela s'est avéré assez long. Et, de plus, il n'est pas fonctionnel, puisque les variables globales sont ici modifiées.
Et maintenant - une autre version de ce code:
from functools import reduce
integers = [1,2,3,4,5,6]
odd_ints = filter(lambda n: n % 2 == 1, integers)
squared_odds = map(lambda n: n * n, odd_ints)
total = reduce(lambda acc, n: acc + n, squared_odds)
C'est un code entièrement fonctionnel. C'est plus court. Il est plus rapide car vous n'avez pas à parcourir de nombreux éléments du tableau. Et, si vous traitez avec les fonctions
filter
, map
et reduce
, il se trouve que ce code n'est pas beaucoup plus difficile à comprendre que celui dans lequel les boucles sont utilisées.
Cela ne signifie pas que dans n'importe quel code de fonction est utilisé
map
, reduce
et d'autres fonctions similaires. Et cela ne signifie pas que pour gérer de telles fonctions, vous devez connaître la programmation fonctionnelle. Le fait est que ces fonctions sont souvent utilisées pour se débarrasser des boucles.
Fonctions ▍Lambda
Quand les gens parlent de l'histoire de la programmation fonctionnelle, ils commencent souvent par parler de l'invention des fonctions lambda. Mais si les fonctions lambda sont sans aucun doute la pierre angulaire de la programmation fonctionnelle, elles ne sont pas la principale cause de la FP.
Les fonctions Lambda sont des outils qui peuvent être utilisés pour écrire des programmes dans un style fonctionnel. Mais ces fonctions peuvent également être utilisées dans la programmation orientée objet.
▍ Saisie statique
L'exemple ci-dessus n'est pas typé statiquement. Mais il s'agit néanmoins d'un exemple de code fonctionnel.
Même si le typage statique ajoute une couche supplémentaire de sécurité à votre code, ce n'est pas une exigence pour la création de code fonctionnel. Cependant, cela peut être un ajout intéressant au style fonctionnel de programmation.
Il est à noter que certains langages sont plus faciles à programmer dans un style fonctionnel que d'autres.
Certaines langues sont "plus fonctionnelles" que d'autres
▍Perl
Perl a une approche pour gérer les effets secondaires qui le distingue de la plupart des autres langages. A savoir, il a une "variable magique"
$_
qui apporte des effets secondaires au niveau de l'une des principales caractéristiques de la langue. Perl a ses mérites, mais je n'essaierais pas de faire de la programmation fonctionnelle dans ce langage.
▍Java
Je vous souhaite la meilleure des chances pour écrire du code Java fonctionnel. Cela ne vous fera pas de mal. Tout d'abord, le mot-clé occupera la moitié du code
static
. Deuxièmement, la plupart des programmeurs Java qualifieront votre code de malentendu.
Cela ne signifie pas que Java est un mauvais langage. Mais il n'est pas conçu pour résoudre le type de problèmes pour lesquels la programmation fonctionnelle est idéale. Par exemple, pour la gestion de bases de données ou pour le développement d'applications d'apprentissage automatique.
▍Scala
Scala est une langue intéressante. Son objectif est d'unifier la programmation fonctionnelle et orientée objet. Si cela vous semble étrange, sachez que vous n'êtes pas seul. Après tout, la programmation fonctionnelle vise à éliminer complètement les effets secondaires. Et la programmation orientée objet consiste à limiter les effets secondaires aux objets.
Dans cet esprit, nous pouvons dire que de nombreux développeurs voient Scala comme un langage qui les aidera à passer de la programmation orientée objet à la programmation fonctionnelle. L'utilisation de Scala peut leur faciliter la transition vers un style de programmation entièrement fonctionnel à l'avenir.
▍Python
Le style de programmation fonctionnel est encouragé en Python. Cela peut être compris si l'on prend en compte le fait que chaque fonction, par défaut, a au moins un paramètre -
self
. C'est, à bien des égards, dans l'esprit de " Zen Python ": "Explicite vaut mieux qu'implicite."
▍Clojure
Clojure, selon le créateur du langage, est fonctionnel à environ 80%. Toutes les valeurs sont immuables par défaut. Mais c'est exactement ce qu'il faut pour écrire du code fonctionnel. Cependant, vous pouvez contourner ce problème en utilisant des conteneurs modifiables, dans lesquels des valeurs immuables sont placées. Et si vous extrayez la valeur du conteneur, elle redevient immuable.
▍Haskell
C'est l'un des rares langages entièrement fonctionnels et typés statiquement. Bien que son utilisation dans le processus de développement puisse sembler trop longue pour implémenter des mécanismes fonctionnels, un tel effort sera récompensé plusieurs fois lors du débogage du code. Cette langue n'est pas aussi facile à apprendre que les autres, mais l'apprendre est certainement un investissement rentable.
Résultat
Il convient de noter que c'est encore le tout début de l'ère du big data. Le Big Data arrive, et pas seul, mais avec un ami - avec une programmation fonctionnelle.
La programmation fonctionnelle, par rapport à la programmation orientée objet, est encore un phénomène de niche. Cependant, si nous considérons l'intégration des principes de FP en Python et dans d'autres langages comme un phénomène significatif, alors nous pouvons conclure que la programmation fonctionnelle gagne en popularité.
Et cela a du sens, car la programmation fonctionnelle se montre bien en travaillant avec des bases de données, en programmation parallèle, dans le domaine de l'apprentissage automatique. Et au cours de la dernière décennie, tout cela a augmenté.
Bien que le code orienté objet présente d'innombrables avantages, vous ne devez pas négliger les avantages du code fonctionnel. Si un programmeur apprend certains des principes de base de la PF, cela peut, dans la plupart des cas, être suffisant pour améliorer son niveau professionnel. Ces connaissances l'aideront également à se préparer à un «futur fonctionnel».
Que pensez-vous de la programmation fonctionnelle?