La différence entre la programmation logique et programmation fonctionnelle

J'ai lu de nombreux articles essayant de comprendre la différence entre la programmation fonctionnelle et la programmation logique, mais la seule déduction que j'ai pu faire jusqu'à présent est que la programmation logique définit des programmes à travers des expressions mathématiques. Mais une telle chose n'est pas associée à la programmation logique.

J'apprécierais vraiment que la lumière soit faite sur la différence entre la programmation fonctionnelle et la programmation logique.

63
demandé sur Wouter Beek 2011-11-28 18:48:31

8 réponses

Je ne dirais pas que la programmation logique définit des programmes à travers des expressions mathématiques; cela ressemble plus à de la programmation fonctionnelle. La programmation logique utilise des expressions logiques (enfin, finalement, la logique est mathématique).

À mon avis, la principale différence entre la programmation fonctionnelle et la programmation logique est les "blocs de construction": la programmation fonctionnelle utilise des fonctions tandis que la programmation logique utilise des prédicats. Un prédicat n'est pas une fonction; il n'a pas de valeur de retour. En fonction de la valeur de ses arguments, il peut être vrai ou faux; si certaines valeurs ne sont pas définies, il essaiera de trouver les valeurs qui rendraient le prédicat vrai.

Prolog utilise en particulier une forme spéciale de clauses logiques nommées clauses Horn {[17] } qui appartiennent à la logique de premier ordre; Hilog utilise des clauses de logique d'ordre supérieur.

Lorsque vous écrivez un prédicat prolog vous définissez une clause horn: foo :- bar1, bar2, bar3. signifie que foo est vrai si bar1, bar2 et bar3 est vrai. notez que je n'ai pas dit si et seulement si; vous pouvez avoir plusieurs clauses pour un prédicat:

foo:-
   bar1.
foo:-
  bar2.

Signifie que foo est vrai si bar1 est vrai ou si bar2 est vrai

Certains disent que la programmation logique est un sur-ensemble de la programmation fonctionnelle, puisque chaque fonction peut être exprimée comme un prédicat:

foo(x,y) -> x+y.

Pourrait être écrit comme

foo(X, Y, ReturnValue):-
   ReturnValue is X+Y.

, Mais je pense que de telles déclarations sont un peu trompeuses

Une autre différence entre logique et fonctionnelle est le retour en arrière. Dans la programmation fonctionnelle une fois que vous entrez le corps de la fonction que vous ne pouvez pas échouer et passez à la définition suivante. Par exemple, vous pouvez écrire

abs(x) -> 
   if x>0 x else -x

Ou même utiliser des gardes:

abs(x) x>0 -> x;
abs(x) x=<0 -> -x.

, Mais vous ne pouvez pas écrire

abs(x) ->
   x>0,
   x;
abs(x) ->
   -x.

D'autre part, dans Prolog vous pouvez écrire

abs(X, R):-
   X>0,
   R is X.
abs(X, R):-
   R is -X.

Si vous appelez abs(-3, R), Prolog essaiera la première clause et échouera lorsque l'exécution atteindra le point -3 > 0 mais vous n'obtiendrez pas d'erreur; Prolog essayera la deuxième clause et retournera R = 3.

Je ne pense pas que il est impossible pour un langage fonctionnel d'implémenter quelque chose de similaire (mais je n'ai pas utilisé un tel langage).

Dans l'ensemble, bien que les deux paradigmes soient considérés comme déclaratifs, ils sont assez différents; si différents que les comparer ressemble à comparer les styles fonctionnels et impératifs. Je suggère d'essayer un peu de programmation logique; ce devrait être une expérience ahurissante. Cependant, vous devriez essayer de comprendre la philosophie et pas simplement écrire des programmes; Prolog vous permet pour écrire dans un style fonctionnel ou même impératif (avec des résultats monstrueux).

57
répondu Thanos Tintinidis 2017-03-30 20:24:16

En un mot:

En programmation fonctionnelle, votre programme est un ensemble de définitions de fonctions. La valeur de retour pour chaque fonction est évaluée comme une expression mathématique, éventuellement en utilisant des arguments passés et d'autres fonctions définies. Par exemple, vous pouvez définir une fonction factorial, qui renvoie une factorielle d'un nombre donné:

factorial 0 = 1                       // a factorial of 0 is 1
factorial n = n * factorial (n - 1)   // a factorial of n is n times factorial of n - 1 

En programmation logique, votre programme est un ensemble de prédicats. Les prédicats sont généralement définis comme des ensembles de clauses, où chaque clause peut être défini à l'aide d'expressions mathématiques, d'autres prédicats définis et de calcul propositionnel. Par exemple, vous pouvez définir un prédicat 'factoriel', qui contient chaque fois que le second argument est une factorielle de first:

factorial(0, 1).               // it is true that a factorial of 0 is 1
factorial(X, Y) :-             // it is true that a factorial of X is Y, when all following are true:
    X1 is X - 1,                   // there is a X1, equal to X - 1,
    factorial(X1, Z),              // and it is true that factorial of X1 is Z, 
    Y is Z * X.                    // and Y is Z * X

Les deux styles permettent d'utiliser des expressions mathématiques dans les programmes.

26
répondu socha23 2011-11-28 15:19:42

Tout d'abord, il y a beaucoup de points communs entre la programmation fonctionnelle et la programmation logique. Autrement dit, beaucoup de notions développées dans une communauté peuvent également être utilisées dans l'autre. Les deux paradigmes ont commencé avec des implémentations plutôt grossières et s'efforcent d'atteindre la pureté.

Mais vous voulez connaître les différences.

Je vais donc prendre Haskell d'un côté et Prolog avec des contraintes de l'autre. Pratiquement tous les systèmes Prolog actuels offrent des contraintes de quelque sorte, comme B, Ciao, ECLiPSe, GNU, IF, SICStus, SWI, YAP, XSB. Pour le bien de l'argument, j'utiliserai une contrainte très simple dif/2 signifiant inégalité, qui était présente même dans la toute première implémentation de Prolog - donc je n'utiliserai rien de plus avancé que cela.

Quelle programmation fonctionnelle manque

La différence La plus fondamentale tourne autour de la notion de variable. En programmation fonctionnelle, une variable désigne une valeur concrète. Cette valeur ne doit pas être entièrement définie, mais seulement les parties définies peuvent être utilisées dans les calculs. Considérez dans Haskell:

> let v = iterate (tail) [1..3] 
> v
[[1,2,3],[2,3],[3],[],*** Exception: Prelude.tail: empty list

Après le 4ème élément, la valeur n'est pas définie. Néanmoins, vous pouvez utiliser les 4 Premiers éléments en toute sécurité:

> take 4 v
[[1,2,3],[2,3],[3],[]]

Notez que la syntaxe dans les programmes fonctionnels est habilement limitée pour éviter qu'une variable ne soit laissée indéfinie.

En programmation logique, une variable n'a pas besoin de se référer à une valeur concrète. Donc, si nous voulons une liste de 3 éléments, nous pourrions dire:

?- length(Xs,3).
Xs = [_G323, _G326, _G329].

Dans cette réponse, les éléments de la liste sont des variables. Toutes les instances possibles de ces variables sont des solutions valides. Comme Xs = [1,2,3]. Maintenant, disons que le premier élément devrait être différent des éléments restants:

?- length(Xs,3), Xs = [X|Ys], maplist(dif(X), Ys).
Xs = [X, _G639, _G642],
Ys = [_G639, _G642],
dif(X, _G642),
dif(X, _G639).

Plus Tard, nous pourrions exiger que les éléments de Xs sont tous égaux. Avant de l'écrire, je vais l'essayer seul:

?- maplist(=(_),Xs).
Xs = [] ;
Xs = [_G231] ;
Xs = [_G231, _G231] ;
Xs = [_G231, _G231, _G231]  ;
Xs = [_G231, _G231, _G231, _G231] .

Vous voyez que les réponses contiennent toujours la même variable? Maintenant, je peux combiner les deux requêtes:

?- length(Xs,3), Xs = [X|Ys], maplist(dif(X), Ys), maplist(=(_),Xs).
false.

Alors ce que nous ont montré ici est qu'il n'y a pas de liste d'éléments 3 où le premier élément est différent des autres éléments et tous les éléments sont égaux.

Cette généralité a permis de développer plusieurs langages de contraintes qui sont proposés comme bibliothèques aux systèmes Prolog, les plus importants étant CLPFD et CHR.

Il N'y a pas de moyen simple d'obtenir des fonctionnalités similaires dans la programmation fonctionnelle. Vous pouvez émuler des choses, mais l'émulation n'est pas tout à fait le de même.

Quelle programmation logique manque

Mais il y a beaucoup de choses qui manquent dans la programmation logique qui rendent la programmation fonctionnelle si intéressante. En particulier:

Programmation D'ordre supérieur: la programmation fonctionnelle a ici une très longue tradition et a développé un riche ensemble d'idiomes. Pour Prolog, les premières propositions remontent au début des années 1980, mais elles ne sont pas encore très courantes. Au moins ISO Prolog a maintenant l'homologue à appliquer appelé call/2, call/3 ....

Lambdas: encore une fois, il est possible d'étendre la programmation logique dans cette direction, le système le plus important est Lambda Prolog. Plus récemment, des lambdas ont également été développés pour ISO Prolog .

Systèmes de Type: il y a eu des tentatives, comme Mercury, mais il n'a pas pris beaucoup. Et il n'y a pas de système avec des fonctionnalités comparables aux classes de type.

Pureté: Haskell est entièrement pur, un entier de fonction - > entier est une fonction. Aucun petits caractères qui rôdent autour. Et encore, vous pouvez effectuer des effets secondaires. Des approches comparables évoluent très lentement.

Il existe de nombreux domaines où la programmation fonctionnelle et logique se chevauchent plus ou moins. Par exemple, le retour en arrière et le relâchement et les compréhensions de liste, l'évaluation paresseuse et freeze/2, when/2, block. DCGs et monades. Je laisse à d'autres le soin de discuter de ces questions...

21
répondu false 2011-11-28 19:00:55

La programmation logique et la programmation fonctionnelle utilisent différentes "métaphores" pour le calcul. Cela affecte souvent la façon dont vous pensez à produire une solution, et signifie parfois que différents algorithmes viennent naturellement à un programmeur fonctionnel qu'un programmeur logique.

Les deux sont basés sur des bases mathématiques qui offrent plus d'avantages pour le code "pur"; code qui ne fonctionne pas avec des effets secondaires. Il existe des langages pour les deux paradigmes qui imposent la pureté, ainsi que des langages cela permet des effets secondaires sans contrainte, mais culturellement les programmeurs de ces langages ont tendance à toujours valoriser la pureté.

Je vais considérer append, une opération assez basique en programmation logique et fonctionnelle, pour ajouter une liste à la fin d'une autre liste.

En programmation fonctionnelle, nous pourrions considérer append comme quelque chose comme ceci:

append [] ys = ys
append (x:xs) ys = x : append xs ys

En programmation logique, nous pourrions considérer append comme quelque chose comme ceci:

append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :- append(Xs, Ys, Zs).

Ces implémenter le même algorithme, et même travailler fondamentalement de la même manière, mais ils "signifient" quelque chose de très différent.

Fonctionnelle append définit la liste qui résulte de l'ajout de ys sur la fin de xs. Nous pensons append comme une fonction à partir de deux listes d'une autre liste, et le système d'exécution est conçu pour calculer le résultat de la fonction lorsque nous invoquons sur deux listes.

Le append logique définit une relation entre trois listes, ce qui est vrai si la troisième liste est les éléments de la première liste, suivis par les éléments de la deuxième liste. Nous pensons à append comme un prédicat qui est vrai ou faux pour 3 listes données, et le système d'exécution est conçu pour trouver des valeurs qui rendront ce prédicat vrai lorsque nous l'invoquons avec des arguments liés à des listes spécifiques et d'autres non liés.

La chose qui rend logique append différent est que vous pouvez l'utiliser pour calculer la liste qui résulte de l'ajout d'une liste à une autre, mais vous peut - aussi utiliser pour calculer la liste, vous devez ajouter sur la fin de l'autre pour obtenir une troisième liste (ou si une telle liste existe), ou pour calculer la liste à laquelle vous devez ajouter un autre pour obtenir une troisième liste, ou pour vous donner deux listes possibles qui peuvent être joints ensemble pour obtenir un troisième (et à explorer tous les possibles façons de le faire).

Tout équivalent en ce que vous pouvez faire tout ce que vous pouvez faire dans l'un dans l'autre, ils conduisent à différents façons de penser à votre tâche de programmation. Pour implémenter quelque chose dans la programmation fonctionnelle, vous réfléchissez à la façon de produire votre résultat à partir des résultats d'autres appels de fonction (que vous devrez peut-être également implémenter). Pour implémenter quelque chose dans la programmation logique, vous pensez aux relations entre vos arguments (dont certains sont en entrée et certains sont en sortie, et pas nécessairement les mêmes d'un appel à l'autre) impliqueront la relation souhaitée.

16
répondu Ben 2011-11-29 03:43:26

Prolog, étant un langage logique, vous donne un retour en arrière gratuit, c'est assez perceptible.

Pour élaborer, et je précise que je ne suis en aucun cas expert dans l'un des paradigmes, il me semble que la programmation logique est bien meilleure quand il s'agit de résoudre les choses. Parce que c'est précisément ce que fait le langage (qui apparaît clairement lorsque le backtracking est nécessaire par exemple).

5
répondu m09 2011-11-28 15:09:11

Je pense que la différence est la suivante:

  • programmation impérative = actions de modélisation
  • fonction programmation = modélisation raisonnement
  • programmation logique = connaissance de la modélisation

Choisissez ce qui vous convient le mieux

4
répondu Periklis Georgiou 2013-01-09 16:08:48

Programmation Fonctionnelle: quand 6PM, lumière sur. la logique de programmation: quand il fait nuit, la lumière sur.

1
répondu Pigeon The 2017-11-01 00:35:06

La différence entre la programmation fonctionnelle et la programmation impérative repose sur deux concepts: -

A: - Que faire ? b:- Comment faire ?

Pensez à un ordinateur comme bébé nouveau-né Maintenant, vous voulez que le bébé pour compléter une tâche (que faire?). Maintenant ce bébé peut soit savoir par lui - même comment accomplir cette tâche s'il sait que sa programmation fonctionnelle. Maintenant si cette baie ne sait pas comment réaliser cette tâche et il a besoin de l'aide des programmeurs pour faire une logique pour ce concept que c'est imperitive de programmation.

-1
répondu Kamran Akbar 2018-07-10 14:34:11