À l'égard de Python, je suis un peu choqué par certains des autres réponses. C'est ce que Andrew Kuchling (Python Programmation Fonctionnelle HOWTO) dit:
Les concepteurs de certains langages informatiques choisir de mettre l'accent sur un particulier
approche de la programmation. Cela les rend souvent difficile l'écriture de programmes
qui utilisent une approche différente. D'autres langues sont multi-paradigme langues
qui prennent en charge plusieurs approches différentes. Lisp, C++ et Python sont
multi-paradigme, vous pouvez écrire des programmes ou des bibliothèques qui sont en grande partie procédurale,
orienté objet, ou fonctionnelle dans toutes ces langues. Dans un grand programme,
les différents articles peuvent être écrits à l'aide de différentes approches; le GUI peut
être orientée objet, tandis que la logique de traitement est de procédure ou fonctionnelle,
par exemple.
Dave Mertz présenté un plus dans(1) profondeur(2) la discussion de la programmation fonctionnelle, en disant:
Résumé: Bien que les utilisateurs pensent généralement de Python comme une procédure
et langage orienté objet, il contient tout ce dont vous avez besoin
pour une approche fonctionnelle de la programmation. Cet article
discute des concepts généraux de la programmation fonctionnelle, et illustre
les moyens de mise en œuvre de techniques fonctionnelles en Python.
Python prend entièrement en charge des fonctions d'ordre supérieur (le premier exemple sur cette page de wikipédia est écrit en Python!). C'est une idée fausse commune. Même si map()
n'ont pas été intégrés, il est trivialement fabriqués par
def map(function, l):
return [function(item) for item in l] # A complete list object is returned
En fait, l'observation de la fonction écrite, de sorte devez en informer immédiatement pourquoi map()
pourrait être considéré comme redondant. L'exemple ci-dessus peut être trivialement convertie en une forme qui renvoie à chaque évaluation de la fonction paresseusement, par la modification de la liste de compréhension dans un générateur:
def map(function, l):
return (function(item) for item in l) # A generator object is returned
Il serait appelé comme ceci:
def dbl(x):
return x + x
for answer in map(dbl, [1,2,3,4,5]):
print answer # Produces 2 4 6 8 10 one per line
Parfois inflammable question de l' lambda
(merci de ne pas débattre de cela avec moi, cette question a été battu à mort dans de loin les plus illustres lieux de ma réponse, je ne suis pas qualifié pour débattre de ce point, etc) est un autre bon exemple:
function = lambda x,y: x + y
print function(2,3) # produces '5'
est complètement équivalente à
def f(x,y):
return x + y
function = f
print function(2,3) # produces '5'
Il n'y a aucune raison de persister avec un mot clé appelé lambda, quand la syntaxe de la langue elle-même fournit la fonctionnalité. La programmation fonctionnelle n'est pas de savoir quelles fonctions sont appelées; il est plus sur la façon dont les choses se font. Pour autant que je suis conscient, la principale carence de Python par rapport à quelque chose comme Régime est l'incapacité à modifier le code lui-même comme un moyen facile, comme la modification d'une liste: ce code est-propriété data est une conséquence de l'utilisation de S-expressions, parce qu'alors tout le code de la syntaxe ressemble à une liste. Python ne le fait pas, ou pas aussi facilement. Si c'est quelque chose que vous voulez obtenir dans, puis c'est à peu près décide le cas pour vous, et vous aurez à se concentrer sur une langue avec des S-expressions/préfixe de notation.
Après avoir dit tout cela, il ya quelques problèmes avec Python comme langage fonctionnel:
Le Mondial de l'Interprète de Verrouillage (GIL) en Python signifie que la division de python fils parmi les multiples séparées cœurs de PROCESSEUR n'est pas possible. IronPython peut ou ne peut pas obtenir autour de cette (exercice laissé au lecteur). L'intérêt d'avoir plusieurs cœurs disponibles, c'est que les langages fonctionnels se prêtent à parallélisables exécution des paradigmes, et vous ne verrez pas un gros avantage de ce stock à l'aide de Python sur une machine multi-coeur. (Dans la pratique, de nombreuses personnes utilisent l'excellent multitraitement paquet dans la bibliothèque standard pour le multi-core de la simultanéité, ou même manuellement lancer plusieurs instances d'une application en ligne de commande avec des scripts shell et ainsi de suite; mais ce sont des considérations pratiques qui n'ont rien à voir avec de la programmation fonctionnelle.)
De ne pas être forcé d'adopter la programmation fonctionnelle, les expressions idiomatiques peut nuire à votre apprentissage. Idiomatiques Python est en aucun cas à proximité du "paradigme de la programmation fonctionnelle", et vous devez sortir de votre façon de coller à un "style", tout simplement parce que plus idiomatiques sont des moyens plus faciles de le faire, et de plus en plus fréquemment recommandé dans la documentation en ligne et des tutoriels. Le Mertz article est d'aider avec cela.
La récursivité. Par défaut, Python a une limite de la récursivité, et il y a la pile C flottant autour de là en arrière-plan lors de l'utilisation de la norme Disponible de distribution. IronPython peut ou pas de traiter de cette question en particulier, mais je ne peux pas dire. Il y a toujours Stackless. De toute façon, c'est quelque chose que vous avez besoin pour regarder dehors pour. Python n'a pas de queue de récursivité, par exemple, pour certains types de "typique" ou "commune" de la programmation fonctionnelle des exemples (fibo()
vient à l'esprit) peut présenter des difficultés de mise en œuvre.
Je sais Python beaucoup, beaucoup mieux que je ne le sais F# (autant que "fonctionnelle" de la programmation va, j'ai peu à modérée de l'expérience avec PLT Régime); et mon en grande partie non informée de l'opinion à ce jour est que le F# se trouve en grande partie dans le même camp que Lisp, Scheme et le devenir rapidement populaire Clojure. Ce sont tous des beaux-langues, mais vous devez être conscient que le travail dans leur signifie que vous êtes assez bien lié à la "programmation fonctionnelle" paradigme (POO en Lisp ne pas ressembler à de la programmation orientée objet dans une autre langue que j'ai vu, indépendamment de ce que les promoteurs peut dire). D'autre part, puisque vous avez dit que vous vouliez apprendre, avec Python, vous pouvez immédiatement comparer et de contraste fonctionnelle-vs-programmation orientée objet-vs-procédure tous dans la même syntaxe; et même dans le même programme. Ce doit être une valeur de quelque chose.
Comic relief: le Y combinator en Python (plus laid Python que vous verrez jamais):
fact = (lambda func:
(lambda f:
func(lambda x:
(f(f))(x)))(lambda f:
func(lambda x:
(f(f))(x))))(lambda f:
lambda n:
1 if n < 2 else n*f(n-1))
print fact(10)
>>>
3628800
EDIT (30 Mars 2011, et éventuellement hors-sujet)
Nathan Sanders fait un bon commentaire:
Votre plateau de la carte exemple ne pas mettre en œuvre la paresse dans le sens généralement utilisé dans le style fonctionnel. Plus précisément, il = map(id, 1); tout(Vrai pour x); tout(Vrai pour x) affiche la valeur True, alors les Faux; il est utilisé par le second appel. C'est un mauvais bug avec une liste plus longue et plusieurs appels à tout."
J'ai eu un peu de temps à tuer et a décidé d'examiner cette question plus loin. Pour commencer, dans mon exemple ci-dessus, qui reste inchangé, la paresse est en effet conservée:
>>> def mymap(f, l):
return (f(item) for item in l)
>>> def dbl(x):
return x + x
>>> # Call 1
>>> for x in mymap(dbl, [1,2,3,4,5]): # Call 1
print(x,end=',')
2,4,6,8,10,
>>> # Call 2
>>> for x in mymap(dbl, [1,2,3,4,5]): # Call 2
print(x,end=',')
2,4,6,8,10,
>>>
Eh bien, dans cet exemple, il n'y a rien ici qui a besoin de préserver, parce que mymap() renvoie un nouvel itérateur chaque fois qu'il est invoqué; cependant, dans l'exemple que Nathan Sanders utilise, l'itérateur renvoyé par la carte n'est en effet utilisée. Ce qui se passe? J'ai fait un simple générateur de fonction pour afficher ce:
>>> def G():
for i in range(10):
yield i
>>> # Create iterator object
>>> g=G()
>>> # Use it
>>> for x in g:
print(x,end=',')
0,1,2,3,4,5,6,7,8,9,
>>> # Use it some more?
>>> for x in g:
print(x,end=',')
>>>
Toutefois, si l'itérateur instance est créée sur place, le problème disparaît:
>>> for x in G():
print(x,end=',')
0,1,2,3,4,5,6,7,8,9,
>>> for x in G():
print(x,end=',')
0,1,2,3,4,5,6,7,8,9,
>>>
Autant que je sache, vous ne pouvez pas redémarrer un générateur, ce qui conduit à la suivante plutôt astucieux et éventuellement carrément trompeuses version de Nathan exemple, qui fonctionne le mieux:
>>> def it():
return map(id, [1])
>>> any(True for x in it())
True
>>> any(True for x in it())
True
>>>
Je ne sais pas quel est l'impact de cette modification pourrait avoir sur la discussion, le cas échéant, mais je suis reconnaissant à Nathan pour piquer mon cerveau un peu.