Existe-t-il un moyen de faire un if dans un prologue, par exemple si une variable est 0, alors faire quelques actions (écrire du texte sur le terminal). Un autre n’est même pas nécessaire, mais je ne trouve aucune documentation sur if.
Un prédicat standard prolog fera cela.
isfive(5).
sera évalué à true si vous l'appelez avec 5 et échouera (retournera false) si vous l'exécutez avec autre chose. Pour pas égal, vous utilisez\=
isNotEqual(A,B):- A\=B.
Techniquement, cela n’unit pas, mais c’est semblable à différent.
Learn Prolog Now est un bon site pour apprendre le prologue.
Edit: Pour ajouter un autre exemple.
isEqual(A,A).
Oui, il existe une telle construction de contrôle dans ISO Prolog, appelée ->
. Vous l'utilisez comme ceci:
( condition -> then_clause ; else_clause )
Voici un exemple utilisant une chaîne de clauses else-if-:
( X < 0 ->
writeln('X is negative. That's weird! Failing now.'),
fail
; X =:= 0 ->
writeln('X is zero.')
; writeln('X is positive.')
)
Notez que si vous omettez la clause else, la condition échouant signifiera que toute l'instruction if échouera. Par conséquent, je recommande de toujours inclure la clause else (même s'il ne s'agit que de true
).
Les prédicats de Prolog "unifient" -
Donc, dans un langage impératif j'écrirais
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
En Prolog j'écrirais
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
ce qui, lorsque vous comprenez les deux styles, est en réalité beaucoup plus clair.
"Je suis bazoo pour le cas particulier où foo a 5 ans"
"Je suis bazoo pour le cas normal où foo n'a pas 5 ans"
J'ai trouvé cela utile pour utiliser une instruction if dans une règle.
max(X,Y,Z) :-
( X =< Y
-> Z = Y
; Z = X
).
Merci à http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html
Tout d’abord, rappelons une logique classique du premier ordre:
" Si P alors Q sinon R" est équivalent à "(P et = Q) ou (non_P et R) ".
Prenons l'exemple concret suivant:
Si
X
est membre de la liste[1,2]
alorsX
est égal à2
sinonX
est égal à4
.
Nous pouvons faire correspondre le modèle ci-dessus (" Si P alors Q sinon R") si ...
P
est list_member([1,2],X)
,non_P
est non_member([1,2],X)
,Q
est X=2
, etR
est X=4
.Pour exprimer des (non) membres de liste de manière pure, nous définissons:
list_memberd ([E | Es], X): - (E = X ; dif (E, X), list_memberd (Es, X) ). non-membre (Es, X): - liste (dif (X), Es).
Voyons maintenant différentes façons d’exprimer "if-then-else" dans Prolog!
(P,Q ; non_P,R)
? liste_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4). [.____] X = 2; X = 4. ? - X = 2, (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 2 . X = 2 ; faux. ? - (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 2. X = 2 ; faux. ? - X = 4, (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 4. ____.] X = 4. ? - (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 4. X = 4.
Score de correction 5/5. Score d'efficacité 3/5.
(P -> Q ; R)
? - (list_memberd ([1,2], X) -> X = 2; X = 4). false. % FAUX ? - X = 2, (list_memberd ([1,2], X) -> X = 2; X = 4), X = 2. X = 2. ? - (list_memberd ([1,2], X) -> X = 2; X = 4), X = 2. false. % FAUX ? - X = 4, (list_memberd ([1,2], X) -> X = 2; X = 4), X = 4. X = 4. ? - (list_memberd ([1,2], X) -> X = 2; X = 4), X = 4. false. % FAUX
Score de correction 2/5. Score d'efficacité 2/5.
(P *-> Q ; R)
? - (list_memberd ([1,2], X) * -> X = 2; X = 4). X = 2 ; faux. % FAUX ? - X = 2, (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 2. X = 2 ; faux. ? - (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 2. X = 2 ; faux. ? - X = 4, (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 4. X = 4. ? - (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 4. false. % FAUX
Score de correction 3/5. Score d'efficacité 1/5.
Résumé (préliminaire):
(P,Q ; non_P,R)
Est correct, mais nécessite une implémentation discrète de non_P
.
(P -> Q ; R)
Perd la sémantique déclarative lorsque l'instanciation est insuffisante.
(P *-> Q ; R)
Est "moins" incomplet que (P -> Q ; R)
, Mais présente toujours des problèmes similaires.
Heureusement pour nous, il y a sont alternatives: Entrez la structure de commande monotone et logique if_/3
!
Nous pouvons utiliser --- (if_/3
avec le prédicat d'adhésion à la liste réifié memberd_t/3
comme suit:
? - if_ (memberd_t (X, [1,2]), X = 2, X = 4). X = 2; X = 4. ? - X = 2, si_ (membred_t (X, [1,2]), X = 2, X = 4), X = 2. X = 2. ? - if_ (memberd_t (X, [1,2]), X = 2, X = 4), X = 2. X = 2 ; faux. ? - X = 4, si_ (membred_t (X, [1,2]), X = 2, X = 4), X = 4. X = 4. ? - if_ (membred_t (X, [1,2]), X = 2, X = 4), X = 4. X = 4.
Score de correction 5/5. Score d'efficacité 4/5.
La meilleure chose à faire est d'utiliser le soi-disant cuts
, qui porte le symbole !
.
if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.
if_then_else(Condition, Action1, Action2) :- Action2.
Ce qui précède est la structure de base d'une fonction de condition.
Pour illustrer cela, voici la fonction max
:
max(X,Y,X):-X>Y,!.
max(X,Y,Y):-Y=<X.
Je suggère de lire plus de documentation sur les coupes, mais en général elles ressemblent à des points d'arrêt. Ex .: Si la première fonction max
renvoie une valeur vraie, la deuxième fonction n'est pas vérifiée.
PS: Je suis assez nouveau sur Prolog, mais c'est ce que j'ai découvert.
Il existe essentiellement trois façons différentes d'exprimer quelque chose comme si-alors-sinon dans Prolog. Pour les comparer, considérons char_class/2
. Pour a
et b
, la classe doit être ab
et other
pour tous les autres termes. On pourrait écrire ceci maladroitement ainsi:
char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
dif(X, a),
dif(X, b).
?- char_class(Ch, Class).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Pour écrire les choses de manière plus compacte, une construction if-then-else est nécessaire. Prolog a un intégré:
?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.
Bien que cette réponse soit valable, elle est incomplète. Seule la première réponse de ( Ch = a ; Ch = b )
Est donnée. Les autres réponses sont coupées. Pas très relationnel, en effet.
Une meilleure construction, souvent appelée "coupe douce" (ne croyez pas le nom, une coupe est une coupe est une coupe), donne des résultats légèrement meilleurs (c'est dans YAP):
?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
Sinon, SICStus a if/3
Avec une sémantique très similaire:
?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
Donc, la dernière réponse est toujours supprimée. Maintenant, entrez library(reif)
pour SICStus , YAP , et SWI . Installez-le et dites:
?- use_module(library(reif)).
?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Notez que tout le if_/3
Est compilé dans un if imbriqué si-alors-sinon pour
char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
qui s'étend dans YAP 6.3.4 à:
char_class(A,B) :-
( A\=a
->
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
;
( A==a
->
B=ab
)
;
A=a,
B=ab
;
dif(A,a),
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
).
Le programme Prolog est en fait une condition importante pour "si" avec "alors" qui imprime "L'objectif est atteint" et "sinon" qui affiche "Aucune définition n'a été trouvée". A, B
Signifie "A est vrai et B est vrai", la plupart des systèmes de prologue n'essaieront pas de satisfaire "B" si "A" n'est pas accessible (c'est-à-dire que X=3, write('X is 3'),nl
imprimera 'X est 3 'quand X = 3, et ne fera rien si X = 2).
( A == B ->
writeln("ok")
;
writeln("nok")
),
La partie else est requise
Vous devriez lire apprendrez maintenant Prolog! Chapitre 10.2 Utiliser Cut . Ceci fournit un exemple:
max(X,Y,Z) :- X =< Y,!, Y = Z.
être dit,
Z
est égal à Y
[~ # ~] si [~ # ~] !
est vrai (ce qui est toujours le cas) [~ # ~] et [~ # ~] X
est <= Y
.