2014-04-23 2 views
0

J'ai toujours pensé cela, mais j'ai besoin d'une confirmation: Le but de la programmation fonctionnelle est de faire du programme écrit une preuve mathématique. Une fois qu'un programme est correctement écrit, il est "prouvé" et devrait fonctionner de la même manière dans n'importe quel environnement. C'est la raison pour laquelle dans FP, il est nécessaire d'avoir un caractère immuable, sinon il n'y a aucune garantie pour l'exactitude de la "preuve", car les changements d'état peuvent introduire des comportements inattendus.Le but de la programmation fonctionnelle

Ai-je raison sur la base de la programmation fonctionnelle?

+3

Je pense plutôt que le but est d'écrire des programmes utiles. – Ingo

+1

Pas vraiment. C'est plus un effet secondaire (heh) qu'un but. Je recommande l'article classique de John Hughes [Why functional programming matters] (http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html). (Et il existe aussi des méthodes de preuve formelle pour les programmes avec état mutable.) – molbdnilo

Répondre

1

Vous n'êtes pas loin de la base, mais je ne le dirais pas comme ça. Je pense que l'objectif principal de la programmation fonctionnelle est de permettre aux programmeurs de raisonner plus facilement sur leur code. Nous ne serons pas toujours capables d'avoir un poof de correction correct, et en effet, la plupart des programmeurs fonctionnels n'en construisent pas un pour leurs programmes. Mais les programmes fonctionnels sont encore plus faciles à raisonner, à mon avis, et c'est l'objectif. Mais comment et pourquoi?

statique vs dynamique

concepts statiques sont liés à code tel qu'il est défini comme vous l'avez lu dans le fichier. Les concepts dynamiques sont liés à la façon dont les données circulent dans votre programme d'un endroit à un autre. Les gens pensent beaucoup mieux statiquement que dynamiquement. Cet argument est fait par Dijkstra dans son papier séminole Go To Statement Considered Harmful. L'argument est qu'il est difficile de comprendre le code si vous avez besoin de garder une trace de la façon dont le pointeur de code circule de manière dynamique. Vous devez essentiellement passer par l'exécution du code. C'est un argument pour exiger qu'au moins le pointeur de code se comporte d'une manière plus statique. Par conséquent, la plupart des langages de programmation n'implémentent pas GOTO mais permettent à la place IF, FOR et WHILE, pour n'en nommer que quelques-uns. C'est ce qu'on appelle la programmation structurée. Ils sont plus faciles à raisonner parce qu'ils sont plus statiques.

L'argument avancé par les programmeurs fonctionnels est que les programmes fonctionnels sont une étape plus restreinte, une étape plus statique, et donc une étape plus facile à raisonner. Dans un programme fonctionnel, votre code est une expression qui évalue à une valeur, pas une série d'énoncés qui mute, donc état dont vous avez besoin de garder une trace dans votre tête afin de comprendre ce qui lui arrive et donc ce qu'il finira par devenir. Je ne dis pas que la programmation fonctionnelle rend cela trivial, mais l'argument est que c'est plus facile. Essayons cela dans un petit exemple. Les expressions sont composées de sous-expressions et on pourrait évaluer ces sous-expressions afin de comprendre leurs valeurs avant de comprendre la valeur de l'expression entière. Essayons de le faire avec un programme fonctionnel simple avec un bug. Ce qui suit est du code Haskell. Supposons que j'évalue «moyenne [1,2,3]» et que j'obtienne «1,5». Ce n'est pas juste! Que puis-je faire? Bien "moyen [1,2,3]" réduit à "1,5". Si je casse la définition de la moyenne dans les deux expressions qui la composent, "total l" et "size l". Je sais que l'argument l est [1,2,3], donc je vais évaluer "total [1,2,3]" et obtenir "6". Cela semble juste mais "taille [1,2,3]" est "4". Ah! Je sais que mon bug est dans la fonction de taille. Donc, je voudrais suivre cela, se retrouver avec "size [] == 1" et se rendre compte que mon cas de base est incorrect. J'aurais dû écrire "alors 0". En revanche, cette stratégie de raisonnement très utile ne fonctionne pas dans la programmation impérative. La raison en est que l'on ne peut extraire une sous-déclaration d'un processus qui modifie l'état pour le comprendre isolément. Une déclaration n'a pas de sens en dehors du contexte de son environnement. Jetons un coup d'oeil à un programme C avec le bug équivalent.

int average (int *l) { 
    int total = 0; 
    int size = 1; 
    int i; 
    for (i = 0; i < sizeof(l); i++) { 
     total = total + l[i]; 
     size = size + 1; 
    } 
    return total/size; 
} 

J'ai le même bug ici comme je l'ai fait la dernière fois, mais maintenant comment puis-je réduire à un problème plus simple pour déboguer mon code? L'instruction "size = size + 1" est une sous-déclaration de mon programme mais cela n'a pas de sens en dehors de son contexte. Je ne peux pas m'assurer que cette sous-déclaration de mon programme fonctionne correctement. Je dois parcourir attentivement le code, en utilisant potentiellement un débogueur et en traçant l'état local pour le voir changer. C'est un processus très dynamique. Les humains pensent beaucoup mieux statiquement.

testabilité

Programmation fonctionnelle est également plus facile à tester l'unité. Prenez, par exemple, ma fonction moyenne d'avant. Toutes les sous-expressions que j'ai mentionnées comme "taille [] == 0" et "taille [1,2,3] == 3" feraient des tests unitaires parfaits. Surtout si ce sont des choses dont je sais que j'ai déjà fait des erreurs! Imaginez si j'essaie de refactoriser ce programme ou de le rendre plus efficace. Ce sera bien d'avoir testé automatiquement de nombreuses petites pièces. Les tests unitaires sont certainement possibles dans la programmation impérative, et les gens le font tout le temps, mais si vous avez une fonction qui prend des données, renvoie des données, et se comporte toujours de la même manière, rien n'est plus facile à tester.

Utiliser la programmation fonctionnelle quand vous pouvez

Pour ces raisons, je pense que les gens, même dans les langues impératives doivent être en train d'écrire autant de leur code que possible de manière fonctionnelle pour le rendre plus facile à tester. Il n'y a aucune raison d'être noir et blanc à ce sujet. C'est un outil, pas une religion. Faire une programmation fonctionnelle à mi-chemin peut grandement augmenter la testabilité et la maintenabilité de votre code.

Pour en savoir plus

Un grand document écrit sur ce sujet, et même celui où je tire beaucoup d'inspiration pour répondre à votre question est Why Functional Programming Matters par John Huges. Aussi, si vous voulez passer par un programme complet conçu pour les programmeurs débutants, je recommande fortement How to Design Programs. Il se concentre vraiment sur l'écriture facilitant le codage par des tests unitaires et la division de votre programme en petites sous-tâches compréhensibles. Ce faisant, je pense qu'il met en évidence ce qui rend la programmation fonctionnelle si puissante.

+0

J'ai déjà suivi un cours de "Langages de programmation" qui utilise SML, Racket et Ruby pour apprendre des paradigmes fonctionnels et impératifs, ainsi que "Introduction à la conception de programme systématique" utilise HtDP pour apprendre. J'ai eu beaucoup de bonnes choses avec la programmation fonctionnelle, et je suis d'accord d'appliquer la PF chaque fois que cela est possible, cela m'aide à être plus productif et à rendre le code plus simple, c'est-à-dire que nous n'avons pas besoin de marcher. Je veux juste comprendre tout le but principal de tout ce que j'ai appris. Merci pour votre réponse. – Amumu

Questions connexes