2012-01-21 5 views
4

Dans Prolog, comment implémentez-vous des prédicats logiques composés comme (A et B) ou (C et D)? Cela peut sembler une simple question, mais de nombreux didacticiels en ligne abordables ne sont pas suffisamment détaillés sur les expressions booléennes. Je suppose que vous ne pouvez pas écrire simplement:Expressions booléennes composées dans Prolog

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D). 

alors comment le feriez-vous?

+4

Si vous aviez essayé d'exécuter ce morceau de code, vous auriez trouvé qu'il fait exactement ce que vous voulez. –

Répondre

19

Comme indiqué par d'autres, votre exemple original

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D). 

est parfaitement valide (en supposant l'analyse syntaxique est comme vous le souhaitez il). Tu n'as pas essayé?

Notions élémentaires

logique ET

foo :- a , b . 

logique OU

foo :- a ; b . 

Combiné

foo :- a , b ; c , d . 

Les Parsis ci-dessus comme:

foo :- (a , b) ; (c , d) . 

Utilisez les parenthèses pour indiquer une autre liaison souhaitée:

foo :- a , (b ; c) , d . 

Mieux encore, évitons l'opérateur ; OU et casser des alternatives en types de clauses distinctes. La séquence est beaucoup plus facile à comprendre pour les gens que la ramification des structures arborescentes. Briser l'alternance en plusieurs clauses simplifie le test/débogage et améliore la compréhension.Par conséquent, préfèrent

foo :- a , b . 
foo :- c , d . 

sur

foo :- a , b ; c , d . 

et préfèrent

foo :- a , bar , d . 

bar :- b . 
bar :- c . 

sur

foo :- a , (b ; c) , d . 

Peut-être le plus important, briser les choses en plusieurs clauses comme celui-ci rend la maintenance plus tard easi er. Avec une structure comme:

foo :- a , b ; c , d . 

Que faites-vous lorsque vous ajoutez un autre cas? Qu'en est-il quand il s'étend à 50 alternatives? Chaque alternative supplémentaire augmente le nombre de chemins de code à travers la clause, rendant ainsi le test et la compréhension plus difficiles. Pour obtenir une couverture de code complète lors des tests, un grand nombre de chemins alternatifs doivent être testés individuellement.

Avec la structure équivalente

foo :- a , b . 
foo :- c , d . 

Ajout d'alternatives est tout simplement une question d'ajouter ou plusieurs clauses supplémentaires, dont chacun peut être testé de manière isolée. Un programmeur professionnel écrit d'abord pour les personnes qui, plusieurs années plus tard, ont besoin de comprendre, de modifier et de corriger ce code (indice: cette personne pourrait être vous-même).

0

test (A, B, C, D): - (cond (A), cond (B)); (cond (C), cond (D)).

+0

pas besoin de la parenthèse ... – m09

+0

@Mog: Pas besoin de parenthèses, mais si vous mélangez les AND et les OR, cela aide à clarifier la précence et la liaison de l'opérateur. Pour beaucoup de gens, une expression comme 'a AND b ou c AND d' n'est pas claire quant à savoir si elle se lie comme' (a et b) OU (c ET d) 'ou se lie-elle comme' a ET (b OR c) et d'? En outre, quel était le but? Ceci est une source assez commune de bugs dans de nombreux langages de programmation, donc il est utile d'indiquer explicitement la liaison souhaitée — l'un des rares endroits, à mon humble avis, où les parenthèses externes font quoi que ce soit pour améliorer le rapport signal/bruit. –

+0

bien sûr, mais ce n'est pas acceptable comme réponse à mon avis, il faudrait au moins préciser qu'il ne fait qu'expliquer les choses et qu'il est équivalent au code d'OP. C'est pourquoi j'ai downvoted. – m09

1

Une alternative simple pour les conjonctions est d'utiliser des sous-stations. Pour les disjonctions, utilisez plusieurs lignes. Votre exemple:

test(A, B, C, D) :- test1(A, B). 
test(A, B, C, D) :- test2(C, D). 
test1(A, B) :- A, B. 
test2(C, D) :- C, D. 

Qu'en est-il de (A ou B) et (C ou D)?

other(A, B, C, D) :- other1(A, B), other2(C, D). 
other1(A, B) :- A. 
other1(A, B) :- B. 
other2(C, D) :- C. 
other2(C, D) :- D. 

Notez que ceci est seulement mentionné comme une alternative à la réponse de joel76.

Questions connexes