プロローグで if を実行する方法はありますか。たとえば、変数が 0 の場合、いくつかのアクションを実行します (端末にテキストを書き込む)。else は必要ありませんが、if のドキュメントが見つかりません。
10 に答える
はい、ISOPrologにはそのような制御構造があり->ます。次のように使用します。
( condition -> then_clause ; else_clause )
else-if-clausesのチェーンを使用する例を次に示します。
( X < 0 ->
writeln('X is negative. That's weird! Failing now.'),
fail
; X =:= 0 ->
writeln('X is zero.')
; writeln('X is positive.')
)
else-clauseを省略した場合、条件が失敗すると、ifステートメント全体が失敗することに注意してください。したがって、else-clauseを常に含めることをお勧めします(たとえそれがちょうどであってもtrue)。
標準のプロローグ述語がこれを行います。
isfive(5).
5 で呼び出した場合は true と評価され、それ以外で実行した場合は失敗 (false を返す) と評価されます。等しくない場合は \= を使用します
isNotEqual(A,B):- A\=B.
技術的には統一ではありませんが、等しくないことに似ています。
Learn Prolog Now は、プロローグを学習するための優れた Web サイトです。
編集:別の例を追加するには。
isEqual(A,A).
プロローグの述語「統一」 -
だから、命令語で私は書くだろう
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
プロローグで私は書くだろう
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
両方のスタイルを理解すると、実際にはより明確になります。
「foo が 5 の特殊なケースでは
バズーです」「foo が 5 でない通常のケースではバズーです」
まず、古典的な一階論理を思い出してみましょう。
" If P then Q else R" は "(P and Q) or (non_P and R)" と同等です。
Prologでは、そのような「if-then-else」をどのように表現できますか?
次の具体例を見てみましょう。
Xが list のメンバーである場合は、[1,2]それ 以外の場合はX等しい2です 。X4
上記のパターン (" If P then Q else R") にマッチできるのは ...
- 状態
Pはlist_member([1,2],X)、 - 否定状態
non_Pはnon_member([1,2],X)、 - 結果
QはX=2、そして - 代替品
RはありませんX=4。
リストの (非) メンバーシップを純粋な方法で表現するには、次のように定義します。
list_memberd([E|Es],X) :-
( E = X
; 差分(E,X),
list_memberd(Es,X)
)。
非メンバー (Es、X) :-
maplist(dif(X),Es)。
Prolog での「if-then-else」のさまざまな表現方法を見てみましょう。
(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 ; 偽。 ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; 偽。 ?- 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)。 偽。% 違う ?- 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. 偽。% 違う ?- 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. 偽。% 違う
正しさスコア 2/5。効率スコア 2/5。
(P *-> Q ; R)?- (list_memberd([1,2],X) *-> X=2 ; X=4)。 X = 2 ; 偽。% 違う ?- 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. X = 2 ; 偽。 ?- 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. 偽。% 違う
正解率 3/5。効率スコア 1/5。
(暫定) 要約:
(P,Q ; non_P,R)は正しいですが、 の個別の実装が必要ですnon_P。(P -> Q ; R)インスタンス化が不十分な場合、宣言的セマンティクスが失われます。(P *-> Q ; R)より「少ない」不完全です(P -> Q ; R)が、それでも同様の問題があります。
幸いなことに、代替手段
があります。論理的に単調な制御構造を入力してくださいif_/3。
次のようif_/3に、具体化された 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 ; 偽。 ?- 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ステートメントを使用する場合に役立ちます。
max(X,Y,Z) :-
( X =< Y
-> Z = Y
; Z = X
).
http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.htmlに感謝します
Prolog で if-then-else のようなものを表現するには、基本的に 3 つの異なる方法があります。それらを比較するには、 を検討してくださいchar_class/2。Foraおよびbクラスは、他のすべての用語に対してabandである必要があります。otherこれは次のようにぎこちなく書くことができます。
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.
したがって、最後の回答はまだ抑制されています。ここで、 SICStus、YAP、およびSWIlibrary(reif)を入力します。それをインストールして、次のように言います。
?- 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
)
).
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関数が真の値を返す場合、2 番目の関数は検証されません。
PS: 私は Prolog にかなり慣れていませんが、これは私が見つけたものです。
Prolog program actually is big condition for "if" with "then" which prints "Goal is reached" and "else" which prints "No sloutions was found". A, Bmeans "A is true and B is true", most of prolog systems will not try to satisfy "B" if "A" is not reachable (i.e. X=3, write('X is 3'),nl will print 'X is 3' when X=3, and will do nothing if X=2).
( A == B ->
writeln("ok")
;
writeln("nok")
),
else の部分は必須です