web-dev-qa-db-fra.com

Pourquoi Python n'est-il pas très utile pour la programmation fonctionnelle?

J'ai toujours pensé que la programmation fonctionnelle pouvait être faite en Python. Ainsi, j’ai été surpris que Python n’ait pas reçu beaucoup de mention dans la question this , et quand cela a été mentionné, ce n’était normalement pas très positif. Cependant, peu de raisons en ont été données (le manque de correspondance de modèle et les types de données algébriques ont été mentionnés). Ma question est donc la suivante: pourquoi Python n'est-il pas très utile pour la programmation fonctionnelle? Y a-t-il plus de raisons que l'absence de correspondance de modèle et de types de données algébriques? Ou bien ces concepts sont-ils si importants pour la programmation fonctionnelle qu'un langage qui ne les prend pas en charge ne peut être qualifié que de langage de programmation fonctionnel de second ordre? (N'oubliez pas que mon expérience en programmation fonctionnelle est assez limitée.)

316
David Johnstone

La question à laquelle vous faites référence demande quelles langues promeuvent à la fois OO et la programmation fonctionnelle. Python ne favorise pas la programmation fonctionnelle même si elle fonctionne assez bien.

Le meilleur argument contre la programmation fonctionnelle dans Python est que les cas d'utilisation impérative/OO sont soigneusement pris en compte par Guido, tandis que les cas d'utilisation de la programmation fonctionnelle ne sont pas. Lorsque j'écris en Python impératif, c'est l'un des plus beaux langages que je connaisse. Lorsque j'écris en Python fonctionnel, il devient aussi laid et désagréable que votre langage moyen qui n'a pas de BDFL .

Ce qui ne veut pas dire que c'est mauvais, mais que vous devez travailler plus fort que si vous passiez à un langage qui promeut la programmation fonctionnelle ou à l'écriture OO Python.

Voici les choses fonctionnelles qui me manquent en Python:


  • Aucune correspondance de modèle et aucune récursion de la queue ne signifient que vos algorithmes de base doivent être écrits impérativement. La récursivité est laide et lente en Python.
  • Une petite bibliothèque de listes et pas de dictionnaires fonctionnels signifie que vous devez écrire beaucoup de choses vous-même.
  • L'absence de syntaxe pour le currying ou la composition signifie que le style sans points est à peu près aussi rempli de ponctuation que d'arguments explicitement passés.
  • Les itérateurs au lieu de listes paresseuses signifient que vous devez savoir si vous voulez de l'efficacité ou de la persistance, et disperser les appels vers list si vous voulez de la persistance. (Les itérateurs sont à usage unique)
  • La syntaxe simple impérative de Python, avec son analyseur LL1 simple, signifie qu'une meilleure syntaxe pour les expressions if et lambda est fondamentalement impossible. Guido aime ça ainsi et je pense qu'il a raison.
381

Guido a une bonne explication à ce sujet ici . Voici la partie la plus pertinente:

Je n'ai jamais considéré que Python était fortement influencé par les langages fonctionnels, peu importe ce que les gens disent ou pensent. J'étais beaucoup plus familiarisé avec les langages impératifs tels que C et ALGOL 68 et bien que j'avais créé des fonctions de première classe, je ne considérais pas Python comme un langage de programmation fonctionnel. Cependant, auparavant, il était clair que les utilisateurs souhaitaient faire beaucoup plus avec les listes et les fonctions.

...

Il convient également de noter que, même si je n’envisageais pas Python _ comme un langage fonctionnel, l’introduction de fermetures a été utile dans le développement de nombreuses autres fonctionnalités de programmation avancées. Par exemple, certains aspects des classes de style nouveau, des décorateurs et d’autres fonctionnalités modernes dépendent de cette capacité.

Enfin, même si un certain nombre de fonctionnalités de programmation fonctionnelles ont été introduites au fil des années, Python ne possède toujours pas certaines fonctionnalités présentes dans les "vrais" langages de programmation fonctionnels. Par exemple, Python n'effectue pas certains types d'optimisations (par exemple, la récursion de la queue). En général, en raison de la nature extrêmement dynamique de Python, il est impossible de réaliser le type d’optimisation à la compilation connue des langages fonctionnels tels que Haskell ou ML. Et c'est bon.

Je tire deux choses de ceci:

  1. Le créateur du langage ne considère pas vraiment Python comme un langage fonctionnel. Par conséquent, il est possible de voir les fonctionnalités "fonctionnelles", mais il est peu probable que vous voyiez quoi que ce soit qui est définitivement fonctionnel.
  2. La nature dynamique de Python inhibe certaines des optimisations que vous voyez dans d'autres langages fonctionnels. Certes, LISP est tout aussi dynamique (sinon plus dynamique) que Python, ce n’est donc qu’une explication partielle.
100
Jason Baker

Scheme n'a pas de types de données algébriques ni de correspondance de motif, mais c'est certainement un langage fonctionnel. Des ennuis à propos de Python d'un point de vue de la programmation fonctionnelle:

  1. Lambda infirme. Comme Lambdas ne peut contenir qu’une expression et que vous ne pouvez pas tout faire aussi facilement dans un contexte d’expression, cela signifie que les fonctions que vous pouvez définir "à la volée" sont limitées.

  2. Les ifs sont des déclarations, pas des expressions. Cela signifie, entre autres choses, que vous ne pouvez pas avoir un lambda avec un if. (Ceci est corrigé par les ternaires dans Python 2.5, mais c'est moche.)

  3. Guido menace de supprimer la carte, filtrer et réduire de temps en temps

D'autre part, python a des fermetures lexicales, des Lambdas et des compréhensions de liste (qui sont vraiment un concept "fonctionnel" que Guido l'admette ou non). Je fais beaucoup de programmation "fonctionnelle" en Python, mais je dirais à peine que c'est idéal.

51
Jacob B

Je n'appellerais jamais Python "fonctionnel", mais chaque fois que je programme en Python, le code finit invariablement par devenir presque purement fonctionnel.

Certes, cela est principalement dû à la très bonne compréhension de la liste. Donc, je ne suggérerais pas nécessairement Python comme langage de programmation fonctionnel, mais je suggérerais une programmation fonctionnelle pour toute personne utilisant Python.

21
Konrad Rudolph

Permettez-moi de démontrer avec un morceau de code tiré d'une réponse à une "fonctionnelle" question Python sur SO

Python:

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = itertools.chain.from_iterable(itertools.imap(kidsFunc, layer))
  return layer

Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation

La principale différence ici est que la bibliothèque standard de Haskell possède des fonctions utiles pour la programmation fonctionnelle: dans ce cas, iterate, concat et (!!)

16
yairchu

Une chose qui est vraiment importante pour cette question (et les réponses) est la suivante: Qu'est-ce que c'est que la programmation fonctionnelle, et quelles en sont les propriétés les plus importantes. Je vais essayer de donner mon point de vue:

La programmation fonctionnelle est un peu comme écrire des mathématiques sur un tableau blanc. Lorsque vous écrivez des équations sur un tableau blanc, vous ne pensez pas à un ordre d'exécution. Il n'y a (généralement) aucune mutation. Vous ne revenez pas le lendemain et vous le regardez, et lorsque vous refaites les calculs, vous obtenez un résultat différent (ou vous pouvez, si vous avez bu du café frais :)). En gros, tout ce qui est sur le tableau est là, et la réponse était déjà là quand vous avez commencé à écrire des choses, vous ne vous êtes pas encore rendu compte de ce que c'était.

La programmation fonctionnelle ressemble beaucoup à cela; vous ne changez pas les choses, vous évaluez simplement l'équation (ou, dans ce cas, le "programme") et déterminez quelle est la réponse. Le programme est toujours là, non modifié. La même chose avec les données.

Voici les caractéristiques les plus importantes de la programmation fonctionnelle: a) la transparence référentielle - si vous évaluez le même énoncé à un autre moment et à un autre endroit, mais avec les mêmes valeurs de variable, cela aura toujours le même sens. b) aucun effet secondaire - peu importe combien de temps vous regardez fixement le tableau blanc, l'équation qu'un autre type est en train de regarder vers un autre tableau blanc ne changera pas accidentellement. c) les fonctions sont aussi des valeurs. qui peut être passé et appliqué avec, ou à, d'autres variables. d) composition de la fonction, vous pouvez faire h = g · f et définir ainsi une nouvelle fonction h(..) qui équivaut à appeler g (f (..)).

Cette liste est classée par ordre de priorité. La transparence référentielle est donc le plus important, suivi de l'absence d'effets secondaires.

Maintenant, si vous parcourez python et vérifiez si le langage et les bibliothèques prennent en charge et garantissent ces aspects, vous êtes sur la bonne voie pour répondre à votre propre question.

14
xeno

Python est presque un langage fonctionnel. C'est "fonctionnel".

Il a des fonctionnalités supplémentaires, donc il n'est pas assez pur pour certains.

Il manque également certaines fonctionnalités, donc ce n'est pas assez complet pour certains.

Les fonctionnalités manquantes sont relativement faciles à écrire. Découvrez des articles comme this sur FP en Python.

11
S.Lott

Une autre raison non mentionnée ci-dessus est que de nombreuses fonctions et méthodes intégrées de types intégrés modifient un objet mais ne renvoient pas l'objet modifié. Le code fonctionnel serait plus propre et plus concis. Par exemple, si some_list.append (some_object) a retourné some_list avec some_object ajouté.

8
Dvd Avins

En plus d'autres réponses, l'une des raisons pour lesquelles Python et la plupart des autres langages multi-paradigmes ne conviennent pas à une programmation véritablement fonctionnelle est que leurs compilateurs/machines virtuelles/temps d'exécution ne prennent pas en charge l'optimisation fonctionnelle. Ce type d’optimisation est obtenu par le compilateur comprenant les règles mathématiques. Par exemple, de nombreux langages de programmation prennent en charge une fonction ou une méthode map. C'est une fonction assez standard qui prend une fonction comme un argument et une itérable comme second argument, puis applique cette fonction à chaque élément de l'itérable.

Quoi qu'il en soit, il s'avère que map( foo() , x ) * map( foo(), y ) est identique à map( foo(), x * y ). Le dernier cas est en réalité plus rapide que le premier car le premier effectue deux copies, le second en effectue une.

De meilleurs langages fonctionnels reconnaissent ces relations basées sur les mathématiques et effectuent automatiquement l'optimisation. Les langues qui ne sont pas dédiées au paradigme fonctionnel ne seront probablement pas optimisées.

4
user2074102