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:
- Fonctions et fermetures de première classe (Ruby, Python et tous les autres que vous avez répertoriés en ont).
- Optimisation des appels de queue garantie (Erlang, Haskell, Scala et Scheme ont cela, mais pas Python, Ruby ou Clojure (encore)).
- Prise en charge de l' immuabilité dans le langage et les bibliothèques standard (c'est un grand que tous les "langages fonctionnels" que vous avez répertoriés (sauf Scheme) mais Ruby et Python n'en ont pas).
- Prise en charge au niveau du langage pour les fonctions référentiellement transparentes (ou pures) (pour autant que je sache, seul Haskell en dispose actuellement).
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:
def add(a, b)
a + b
end
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).