En utilisant des générateurs et lambda, nous pouvons faire de la programmation fonctionnelle avec Python. Vous pouvez également réaliser la même chose avec Ruby.
La question est donc: pourquoi avons-nous besoin de langages de programmation fonctionnels spécifiques tels que Erlang, Haskell et Scheme? Y a-t-il quelque chose de différent que ces langages de programmation fonctionnels spécifiques fournissent? Pourquoi ne pouvons-nous pas simplement utiliser Python pour la programmation fonctionnelle?
programming-languages
python
functional-programming
Joshua Partogi
la source
la source
Réponses:
J'apprécie la question, car je suis personnellement un grand fan à la fois du style de programmation Python et fonctionnel. J'ai une longue expérience en Python et j'ai commencé à apprendre Haskell récemment, alors voici quelques points basés sur mes expériences personnelles sur les différences entre ces langues aussi, d'un point de vue fonctionnel.
Pureté
Même si vous ne vous souciez pas de la pureté des fonctions (c'est-à-dire de l'absence d'effets secondaires) en tant que principe, cela a un effet pratique sur la facilité avec laquelle il est possible de lire le code et de le raisonner. Même si vous maintenez la pureté dans vos propres fonctions Python, il y a une grande différence à ce que le compilateur applique la pureté et, surtout, que la bibliothèque standard soit construite en termes de pureté et de structures de données immuables.
Performance
Vous pouvez ou non vous soucier des performances en fonction de votre domaine d'application, mais le typage statique et la pureté garantie donnent beaucoup plus de travail au compilateur, par rapport à Python et à d'autres langages dynamiques (bien que je dois admettre que PyPy fait de grands incursions, et par exemple LuaJIT est proche de miraculeux).
Optimisation des appels de queue
Lié aux performances, mais légèrement différent. Même si vous ne vous souciez pas trop des performances d'exécution, l'absence d'optimisation des appels de queue (en particulier pour la récursivité de queue) limite les façons dont vous pouvez implémenter des algorithmes en Python sans atteindre les limites de la pile.
Syntaxe
C'est la principale raison pour laquelle j'ai commencé à regarder les "vrais" langages fonctionnels au lieu d'utiliser simplement Python avec un style fonctionnel. Bien que je pense que Python a une syntaxe très expressive en général, il a quelques points faibles spécifiques au codage fonctionnel. Par exemple:
f = g . h
rapport àf = lambda *arg: g(h(*arg))
f = map g
Vsf = functools.partial(map, g)
sum = reduce (+) lst
rapport auxsum = reduce(operator.add, lst)
y = func1 $ func2 $ func3 x
plus facile à lire quey = func1(func2(func3(x)))
, une fois que vous êtes familiarisé avec cette notation.la source
Ce sont les différences les plus importantes:
Haskell
Haskell et Erlang
Erlang
Schème
Toutes les langues
En outre, vous devriez jeter un œil aux langages de la famille ML comme SML, Ocaml et F # et Scala, qui fusionnent OO et la programmation fonctionnelle d'une nouvelle manière. Toutes ces langues ont des caractéristiques intéressantes uniques.
la source
Il est difficile de définir exactement ce qu'est un «langage fonctionnel» - parmi les langages que vous avez énumérés, seul Haskell est purement fonctionnel (tous les autres adoptent une sorte d'approche hybride). Cependant, certaines fonctionnalités de langage sont très utiles pour la programmation fonctionnelle, et Ruby et Python n'en ont pas assez pour être de très bons environnements pour FP. Voici ma liste de contrôle personnelle, par ordre d'importance:
La nécessité de (1) devrait être évidente - les fonctions d'ordre supérieur sont extrêmement difficiles sans fonctions de première classe. Lorsque les gens disent que Ruby et Python sont de bons langages pour la PF, ils en parlent généralement. Cependant, cette caractéristique particulière est nécessaire mais pas suffisante pour rendre un langage bon pour la PF.
(2) est une nécessité traditionnelle pour la PF depuis que Scheme a été inventé. Sans TCO, il est impossible de programmer avec une récursion profonde, qui est l'une des pierres angulaires de FP, car vous obtenez des débordements de pile. Le seul langage "fonctionnel" (par définition populaire) qui n'en dispose pas est Clojure (en raison des limitations de la JVM), mais Clojure a une variété de hacks pour simuler le TCO. (Pour info, Ruby TCO est spécifique à l'implémentation , mais Python ne le prend pas spécifiquement en charge .) La raison pour laquelle le TCO doit être garanti est que s'il est spécifique à l'implémentation, les fonctions récursives profondes vont rompre avec certaines implémentations, donc vous ne pouvez pas vraiment les utiliser du tout.
(3) est une autre grande chose que les langages fonctionnels modernes (en particulier Haskell, Erlang, Clojure et Scala) ont que Ruby et Python n'ont pas. Sans entrer dans trop de détails, l'immuabilité garantie élimine des classes entières de bogues, en particulier dans des situations simultanées, et permet des choses soignées comme des structures de données persistantes . Il est très difficile de profiter de ces avantages sans un support au niveau de la langue.
(4) est, pour moi, la chose la plus intéressante à propos des langages purement fonctionnels (par opposition aux langages hybrides). Considérez la fonction Ruby extrêmement simple suivante:
Cela ressemble à une fonction pure, mais en raison de la surcharge de l'opérateur, elle peut muter l'un des paramètres ou provoquer des effets secondaires tels que l'impression sur la console. Il est peu probable que quelqu'un surcharge l'
+
opérateur pour avoir un effet secondaire, mais le langage ne donne aucune garantie. (La même chose s'applique à Python, mais peut-être pas avec cet exemple spécifique.)Dans un langage purement fonctionnel, en revanche, il existe des garanties au niveau du langage que les fonctions sont référentiellement transparentes. Cela présente de nombreux avantages: les fonctions pures peuvent être facilement mémorisées; ils peuvent être facilement testés sans dépendre d'aucune sorte d'état global; et les valeurs de la fonction peuvent être évaluées paresseusement ou en parallèle sans se soucier des problèmes de concurrence. Haskell en profite pleinement, mais je ne connais pas suffisamment les autres langages fonctionnels pour savoir s'ils le font.
Cela étant dit, il est possible d'utiliser les techniques de FP dans presque tous les langages (même Java). Par exemple, MapReduce de Google est inspiré par des idées fonctionnelles, mais pour autant que je sache, ils n'utilisent aucun langage "fonctionnel" pour leurs grands projets (je pense qu'ils utilisent principalement C ++, Java et Python).
la source
Les langues que vous mentionnez sont très différentes.
Alors que Python et Ruby sont des langages typés dynamiquement, Haskell est typé statiquement. Erlang est une langue simultanée et utilise le modèle Actor et est très différent de toutes les autres langues que vous mentionnez.
Python et Ruby ont de nombreuses constructions impératives alors que dans un langage fonctionnel plus pur comme Haskell, tout renvoie quelque chose ou en d'autres termes tout est une fonction.
la source
En retard à la fête comme d'habitude, mais je vais quand même dire des choses.
Un langage de programmation fonctionnel n'est pas un langage qui permet une programmation fonctionnelle. Si nous devions suivre cette définition, alors pratiquement n'importe quel langage n'importe où est un langage de programmation fonctionnel. (La même chose s'applique à la POO, soit dit en passant. Vous pouvez écrire dans un style de POO en C si vous le souhaitez. Ainsi, selon votre logique, C est un langage de POO.)
Ce qui fait qu'un langage de programmation fonctionnel n'est pas ce qu'il vous permet de programmer comme, c'est ce qu'il vous permet de programmer facilement . Voilà la clé.
Ainsi, Python a des lambdas (qui sont des affaires incroyablement anémiques) et vous offre quelques fonctions de bibliothèque que vous verrez dans les bibliothèques fonctionnelles ainsi que "map" et "fold". Cependant, cela ne suffit pas pour en faire un langage de programmation fonctionnel, car il est difficile, voire impossible, de le programmer de manière cohérente dans un style fonctionnel approprié (et le langage n'applique certainement pas ce style!). À la base, Python est un langage impératif concerné par les opérations d'état et de manipulation d'état, ce qui est tout simplement contraire à l'expression et à la sémantique d'évaluation des expressions d'un langage fonctionnel.
Alors pourquoi avons-nous des langages de programmation fonctionnels quand Python (ou Ruby (ou insérez le langage de votre choix)) peut "faire de la programmation fonctionnelle"? Parce que Python, et al ne peuvent pas faire une programmation fonctionnelle appropriée. Voilà pourquoi.
la source
Vous pouvez faire de la programmation fonctionnelle en Java (voir par exemple http://functionaljava.org/ ). Vous pouvez aussi faire la programmation orientée objet en C . Ce n'est tout simplement pas si idiomatique.
Donc, en effet, nous n'avons absolument pas besoin d'Erlang, Haskell, Scheme ou d'un langage de programmation spécifique, mais ils représentent tous des approches et des compromis différents, ce qui rend certaines tâches plus faciles et plus difficiles. Ce que vous devez utiliser dépend de ce que vous souhaitez réaliser.
la source
Cette question peut être appliquée à un nombre infini de langues et de paradigmes.
La plupart, sinon toutes les langues existent pour une raison spécifique. Ils existent parce que quelqu'un avait un besoin qu'aucune langue courante ne remplissait ou mal rempli. (Bien sûr, cela ne s'applique pas à toutes les langues, mais je pense que cela s'applique à la plupart des langues bien connues.) Par exemple, python a été initialement développé pour s'interfacer avec le système d'exploitation Amoeba [ 1 , 2 ] et Erlang a été créé pour aider dans le développement d'applications de téléphonie [ 3 ]. Donc une réponse à la question "Pourquoi avons-nous besoin d'un autre langage fonctionnel?" peut simplement l'être, car [insérer-nom-de-quelqu'un-qui-sait-comment-concevoir-les langages] n'a pas aimé la façon dont python l'a fait.
Cela résume à peu près ce que je pense que la réponse est. Alors que vous pouvez faire avec python tout ce que vous pouvez faire avec un langage fonctionnel, le voudriez-vous vraiment? Tout ce que vous pouvez faire en C, vous pouvez le faire en assemblage, mais le voudriez-vous? Différentes langues seront toujours les meilleures pour faire des choses différentes, et c'est ainsi que cela devrait être.
la source
La programmation fonctionnelle concerne autant un paradigme de conception que des fonctionnalités de langage spécifiques. Ou, autrement dit, lambdas et une fonction de carte ne font pas un langage de programmation fonctionnel. Python et Ruby ont certaines fonctionnalités inspirées des langages de programmation fonctionnels, mais vous écrivez toujours généralement du code de manière très impérative. (C'est un peu comme C: vous pouvez écrire du code de type OO en C, mais personne ne considère sérieusement C comme un langage OO.)
Regardez: la programmation fonctionnelle ne concerne pas seulement les lambdas
map
ou les fonctions d'ordre supérieur. Il s'agit de design . Un programme écrit dans un "vrai" langage de programmation fonctionnel résout les problèmes via la composition des fonctions. Bien que les programmes écrits en Ruby ou Python puissent utiliser des fonctionnalités de type FP, ils ne lisent généralement pas comme un ensemble de fonctions composées.la source
Chaque langage fonctionnel que vous avez mentionné s'intègre assez bien dans une certaine niche et les modèles idiomatiques que chacun encourage les rendent très bien adaptés à certaines tâches qui seraient impossibles à accomplir en Python à moins d'avoir construit une énorme bibliothèque de modules d'assistance. Le plus évident d'une telle excellence de niche est le modèle de concurrence d'Erlang. Les autres ont également des forces similaires.
la source
Chaque concept disponible en lambda-calcul, LISP et Scheme est disponible en Python, donc, oui, vous pouvez y faire une programmation fonctionnelle. Si c'est pratique ou non, c'est une question de contexte et de goût.
Vous pouvez facilement écrire un interpréteur LISP (ou autre langage fonctionnel) en Python (Ruby, Scala) (qu'est-ce que cela signifie?). Vous pouvez écrire un interpréteur pour Python en utilisant purement fonctionnel, mais cela prendrait beaucoup de travail. Même les langages "fonctionnels" sont aujourd'hui multi-paradigmes.
Ce vieux et beau livre contient la plupart (mais pas toutes) des réponses sur l'essence de la programmation fonctionnelle.
la source
eval()
fonction, qui est nécessaire pour que le code soit des données , mais cela va plus loin: il vous permet de modifier la plupart de l'environnement d'exécution, comme dans LISP.eval()
est une métaprogrammation d'exécution. Parfois, c'est utile, mais c'est extrêmement cher. Les macros Lisp sont différentes, c'est une métaprogrammation en temps de compilation. Il n'est disponible en Python sous aucune forme utilisable.Parce que Python peut également programmer dans un style non fonctionnel, et ce n'est pas suffisant pour le puriste FP. Les codeurs plus pragmatiques, cependant, peuvent profiter des avantages du style fonctionnel sans être dogmatique à ce sujet:
- John Hughes, Pourquoi la programmation fonctionnelle est importante
la source
goto
est terrible.call-with-current-continuation
.