32 votes

Python vs F#: quelle langue je dois apprendre

Hey, je sais que c'est une question subjective, mais merci de ne pas voter pour le fermer avant que je reçois la réponse acceptable.

Je suis une .NET programmeur (un peu connu), et je veux vraiment apprendre un langage fonctionnel. Mes choix sont F# et Python, et j'ai vraiment des doutes sur lequel choisir. Veuillez effacer mes doutes. Je suis totalement nouveau avec eux à la fois, alors merci de me dire leurs avantages les uns sur les autres, ou pourquoi je devrais choisir F#/Python.

Je suis peut-être trompeuses, mais Wikipedia dit que:

F# (prononcez F Sharp) est un multi-paradigme langage de programmation, le ciblage de la .NET Framework, qui englobe la programmation fonctionnelle comme bien que l'impératif de l'orienté objet programmation disciplines.

et:

Python prend en charge plusieurs de programmation paradigmes, principalement, mais non limité orientés objet, impératif et, à une moindre mesure, fonctionnel styles de programmation.

Merci à l'avance.

71voto

Rafe Points 3297

Je doute que vous allez apprendre beaucoup de valeur à partir de Python. C'est un typées dynamiquement langage OO avec agréablement léger de la syntaxe. D'autres que de vous donner encore moins de protection (et la vitesse) que vous obtenez à partir de C#, vous devrez écrire les mêmes programmes, juste un peu différente de dialecte.

F# est une bête différente tout à fait. Il dispose d'un riche, statiquement cochée, polymorphe, algébrique type de système. C'est surtout fonctionnel, ce qui signifie qu'il vous encourage fortement à programmer de manière déclarative et éviter les effets secondaires (comme la cession) dans la mesure du possible. Ceci a plusieurs avantages:

  • le compilateur va attraper beaucoup plus d'erreurs que vous allez être utilisés pour;

  • vos programmes seront beaucoup plus courtes;

  • vos programmes fonctionnent première fois (une fois que le compilateur a pressé tous les bugs qu'il peut trouver) environ neuf fois sur dix, dans mon expérience;

  • le compilateur peut généralement de générer beaucoup plus, beaucoup mieux le code.

J'ai l'habitude de compter qu'il prend un impératif programmeur environ un mois pour faire tourner leur pensée dans le style fonctionnel. L'inconvénient est qu'après le réglage, la programmation ordinaire se sent juste assez primitif et maladroit.

Allez-y, c'est ouvrir les yeux.

45voto

cjrh Points 3960

À 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.

21voto

Brian Points 82719

Voici quelques faits sur les langues (je sais plus sur F# je suis susceptible d'avoir le biais de ce qui peut informer de votre décision.

  • F# est fourni à l'intérieur de Visual Studio et est un .NET de la langue, donc si vous savez que plate-forme/outils, c'est un avantage pour décoller. Fer Python est un .NET Python de mise en œuvre qui a aussi quelques VS prise en charge comme un complément.
  • Les deux langues ont REPLs. F# est compilé (même dans le REPL il sera compilé à la volée), a donc de bonnes performances à la fois comme une application compilée et dans le REPL. (Pas sûr de Python.)
  • F# est "plus fonctionnel" par une variété de critères, donc si vous voulez vraiment "fonctionnelle", je choisirais F# sur Python pour cette seule raison.
  • F# est statiquement typé. Python est dynamique.
  • Les deux langues sont souvent utilisés dans les sciences et les mathématiques domaines; je pense que Python est plus et est de plus en plus (et plus mature) numériques des bibliothèques.
  • Vous pouvez utiliser F# et le Fer Python ensemble en concert (j'ai vu quelques blogs qui montrent base des démos de cela) si vous voulez faire les deux.

8voto

mipadi Points 135410

Python n'est pas vraiment un langage fonctionnel. Bien sûr, il a des constructions fonctionnelles (le premier de la classe des fonctions, etc.) mais vous êtes encore (en général), la programmation a décidément un impératif, style procédural avec Python. F# adhère plus étroitement à le paradigme fonctionnel.

7voto

Yin Zhu Points 10438

Python n'est pas fonctionnelle. Si vous souhaitez utiliser un langage fonctionnel, vous devriez certainement aller avec F#.

Si vous google "python programmation fonctionnelle", vous pouvez le voir il y a peu de choses là. Python la philosophie de ne pas encourager la programmation fonctionnelle soit. C'est pourquoi la nouvelle Python 3.0 supprime certains éléments fonctionnels de Python 2.x.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X