Selon Pippenger [1996] , lorsque l'on compare un système Lisp qui est purement fonctionnel (et a une sémantique d'évaluation stricte, pas paresseux) à un système qui peut muter des données, un algorithme écrit pour le Lisp impur qui s'exécute en O ( n ) peut être traduit à un algorithme en Lisp pur qui s'exécute en temps O ( n log n ) (basé sur les travaux de Ben-Amram et Galil [1992] sur la simulation de la mémoire à accès aléatoire en utilisant uniquement des pointeurs). Pippenger établit également qu'il existe des algorithmes pour lesquels c'est le mieux que vous puissiez faire; il y a des problèmes qui sont O ( n ) dans le système impur qui sont Ω ( n log n ) dans le système pur.
Il y a quelques mises en garde à faire sur ce document. Le plus important est qu'il ne traite pas des langages fonctionnels paresseux, tels que Haskell. Bird, Jones et De Moor [1997] démontrent que le problème construit par Pippenger peut être résolu dans un langage fonctionnel paresseux en temps O ( n ), mais ils n'établissent pas (et pour autant que je sache, personne ne l'a) si ou pas un langage fonctionnel paresseux ne peut résoudre tous les problèmes dans le même temps d'exécution asymptotique qu'un langage avec mutation.
Le problème construit par Pippenger nécessite que Ω ( n log n ) soit spécifiquement construit pour atteindre ce résultat, et n'est pas nécessairement représentatif des problèmes pratiques du monde réel. Il y a quelques restrictions sur le problème qui sont un peu inattendues, mais nécessaires pour que la preuve fonctionne; en particulier, le problème nécessite que les résultats soient calculés en ligne, sans pouvoir accéder aux futures entrées, et que l'entrée soit constituée d'une séquence d'atomes provenant d'un ensemble illimité d'atomes possibles, plutôt que d'un ensemble de taille fixe. Et l'article établit uniquement des résultats (borne inférieure) pour un algorithme impur de temps de parcours linéaire; pour les problèmes qui nécessitent un temps d'exécution plus long, il est possible que le O supplémentaire (log n), le facteur observé dans le problème linéaire peut être «absorbé» au cours d'opérations supplémentaires nécessaires pour les algorithmes avec des temps d'exécution plus longs. Ces clarifications et questions ouvertes sont explorées brièvement par Ben-Amram [1996] .
En pratique, de nombreux algorithmes peuvent être implémentés dans un langage fonctionnel pur avec la même efficacité que dans un langage avec des structures de données mutables. Pour une bonne référence sur les techniques à utiliser pour implémenter efficacement des structures de données purement fonctionnelles, voir "Purely Functional Data Structures" de Chris Okasaki [Okasaki 1998] (qui est une version étendue de sa thèse [Okasaki 1996] ).
Quiconque a besoin d'implémenter des algorithmes sur des structures de données purement fonctionnelles doit lire Okasaki. Vous pouvez toujours obtenir au pire un ralentissement O (log n ) par opération en simulant la mémoire mutable avec un arbre binaire équilibré, mais dans de nombreux cas, vous pouvez faire beaucoup mieux que cela, et Okasaki décrit de nombreuses techniques utiles, des techniques amorties aux techniques réelles. ceux qui effectuent le travail amorti progressivement. Les structures de données purement fonctionnelles peuvent être un peu difficiles à travailler et à analyser, mais elles offrent de nombreux avantages, tels que la transparence référentielle, qui sont utiles dans l'optimisation du compilateur, dans l'informatique parallèle et distribuée et dans la mise en œuvre de fonctionnalités telles que la gestion des versions, l'annulation et la restauration.
Notez également que tout cela ne traite que des temps de fonctionnement asymptotiques. De nombreuses techniques pour implémenter des structures de données purement fonctionnelles vous donnent un certain ralentissement constant des facteurs, en raison de la tenue de livres supplémentaire nécessaire pour qu'elles fonctionnent et des détails d'implémentation de la langue en question. Les avantages des structures de données purement fonctionnelles peuvent l'emporter sur ces ralentissements constants des facteurs, vous devrez donc généralement faire des compromis en fonction du problème en question.
Références
- Ben-Amram, Amir et Galil, Zvi 1992. "On Pointers versus Addresses" Journal de l'ACM, 39 (3), pp. 617-648, juillet 1992
- Ben-Amram, Amir 1996. "Notes on Pippenger's Comparison of Pure and Impure Lisp" Manuscrit non publié, DIKU, Université de Copenhague, Danemark
- Bird, Richard, Jones, Geraint et De Moor, Oege 1997. "Plus de hâte, moins de vitesse: évaluation paresseuse contre désireuse" Journal of Functional Programming 7, 5 p. 541–547, septembre 1997
- Okasaki, Chris 1996. "Structures de données purement fonctionnelles" Thèse de doctorat , Université Carnegie Mellon
- Okasaki, Chris 1998. "Structures de données purement fonctionnelles" Cambridge University Press, Cambridge, Royaume-Uni
- Pippenger, Nicholas 1996. "Pure Versus Impure Lisp" Symposium ACM sur les principes des langages de programmation, pages 104–109, janvier 1996