プロローグで 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
です 。X
4
上記のパターン (" 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
クラスは、他のすべての用語に対してab
andである必要があります。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, B
means "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 の部分は必須です