"если" в прологе?
вероятно, глупый вопрос,но я не могу найти никакой документации для него. Есть ли способ сделать if в prolog, например, если переменная равна 0, то выполнить некоторые действия (написать текст в терминал). Другое даже не нужно, но я не могу найти никакой реализации if.
10 ответов
стандартный предикат prolog сделает это.
isfive(5).
будет оценивать true, если вы вызываете его с помощью 5 и fail (return false), если вы запустите его с чем-либо еще. Для не равных вы используете \=
isNotEqual(A,B):- A\=B.
технически это не объединяет,но это похоже на не равно.
Learn Prolog Now-хороший сайт для изучения пролога.
изменить: Чтобы добавить еще один пример.
isEqual(A,A).
да, в ISO Prolog есть такая управляющая конструкция, называемая ->
. Вы используете его так:
( condition -> then_clause ; else_clause )
вот пример, который использует цепочку предложений else-if:
( X < 0 ->
writeln('X is negative. That's weird! Failing now.'),
fail
; X =:= 0 ->
writeln('X is zero.')
; writeln('X is positive.')
)
обратите внимание, что если вы опустите предложение else, условие failing будет означать, что весь оператор if потерпит неудачу. Поэтому я рекомендую всегда включать предложение else (даже если это просто true
).
предикаты пролога 'unify' -
Итак, в императивном langauge я бы написал
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
в прологе я бы написал
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
что, когда вы понимаете, оба стиля, на самом деле намного яснее.
"Я базу для особого случая, когда фу 5"
"Я базу для нормального случая, когда фу не 5"
Я нашел это полезным для использования если оператор в правиле.
max(X, Y, Z) :- (X =Z = Y ; Z = X).
спасибо http://cs.union.edu / ~striegnk/learn-prolog-now/html/node89.html
лучше всего использовать так называемый cuts
, который имеет символ !
.
if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.
if_then_else(Condition, Action1, Action2) :- Action2.
вышеуказанное основная структура функции условия.
чтобы проиллюстрировать, вот max
функция:
max(X,Y,X):-X>Y,!.
max(X,Y,Y):-Y=<X.
Я предлагаю прочитать больше документации по сокращениям, но в целом они похожи на точки останова.
Бывший.: В случае первой max
функция возвращает значение true, вторая функция не проверено.
PS: Я довольно новичок в Prolog, но это то, что я узнал.
во-первых, давайте вспомним классическую логику первого порядка:
"если P затем Q другое R " эквивалентно "(P и Q)или (non_P и R)".
как мы можем выразить "если-то-иначе" как это в прологе?
рассмотрим следующий конкретный пример:
если
X
является членом затемX
равна2
другоеX
равна4
.
мы можем соответствовать над картиной ("если P затем Q другое R") если ...
- условие
P
islist_member([1,2],X)
, - отрицается условие
non_P
isnon_member([1,2],X)
, - следствие
Q
isX=2
и - альтернатива
R
isX=4
.
чтобы выразить список (не-)членство в чистом виде, мы определяем:
list_memberd([E|Es],X) :- ( E = X ; dif(E,X), list_memberd(Es,X) ). non_member(Es,X) :- maplist(dif(X),Es).
давайте проверим различные способы выражения "если-то-иначе" в прологе!
-
(P,Q ; non_P,R)
?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4). X = 2 ; X = 4. ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4.
оценка правильности 5/5. Оценка эффективности 3/5.
-
(P -> Q ; R)
?- (list_memberd([1,2],X) -> X=2 ; X=4). false. % WRONG ?- 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. % WRONG ?- 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. % WRONG
оценка правильности 2/5. Оценка эффективности 2/5.
-
(P *-> Q ; R)
?- (list_memberd([1,2],X) *-> X=2 ; X=4). X = 2 ; false. % WRONG ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- 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. % WRONG
оценка правильности 3/5. Оценка эффективности 1/5.
(предварительный) резюме:
(P,Q ; non_P,R)
правильная, но нуждается в дискретной реализацииnon_P
.(P -> Q ; R)
теряет декларативную семантику при недостаточном создании экземпляра.(P *-> Q ; R)
"меньше", чем неполные(P -> Q ; R)
, но все еще имеет подобные проблемы.
к счастью для нас, есть are альтернативы:
введите логически монотонную конструкцию управления if_/3
!
можно использовать if_/3
вместе с предикатом reified list-membership memberd_t/3
вот так:
?- if_(memberd_t(X,[1,2]), X=2, X=4). X = 2 ; X = 4. ?- X=2, if_(memberd_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 ; false. ?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4. ?- if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4.
оценка правильности 5/5. Оценка эффективности 4/5.
есть по существу три разных способа выразить что-то вроде if-then-else в прологе. Чтобы сравнить их рассмотрим char_class/2
. Для a
и b
класса необходимо ab
и other
для всех остальных условия. Можно было бы написать это так неуклюже:--17-->
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).
чтобы писать вещи более компактно, нужна конструкция if-then-else. Prolog имеет встроенный:
?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.
хотя этот ответ звучит, он неполон. Только первый ответ от ( Ch = a ; Ch = b )
дается. Остальные ответы отрезаны. В самом деле, не очень близкие отношения.
лучшая конструкция, часто называемая "мягким вырезом" (не верьте названию, разрез-это разрез-это разрез), дает немного лучшие результаты (это в YAP):
?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
альтернативно, SICStus имеет if/3
С очень похожей семантики:
?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
таким образом, последний ответ все еще подавлен. Теперь введите library(reif)
на SICStus, YAP, и SWI. Установите его и скажите:
?- 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).
обратите внимание, что все if_/3
компилируется в дико вложенный if-then-else для
char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
который расширяется в 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
)
).
программа Prolog на самом деле является большим условием для "Если" с "ТО", который печатает "цель достигнута" и "еще", который печатает "не было найдено sloutions". A, B
означает "a истинно и B истинно", большинство систем пролога не будут пытаться удовлетворить" B", если" A " недоступно (т. е. X=3, write('X is 3'),nl
будет печатать "X равно 3", Когда X=3, и ничего не будет делать, если X=2).
следует читать Узнайте Пролог Сейчас! Глава 10.2 Использование Cut. Это дает пример:
max(X,Y,Z) :- X =< Y,!, Y = Z.
сказано,
Z
равна Y
если !
истинно (что всегда так)и X
is <= Y
.