指摘されたように、Prolog は手続き型思考にうまく対応していません。
Prolog プログラムとその「データベース」をツリー (フォレスト?) と考える最良の方法を見つけました。グラフにはサイクル (再帰) が含まれているため、類推は少し大雑把です。
プロローグ エンジンに特定のアサーション (述語) の真偽を判断するように依頼すると、統合 (パターン マッチング) を使用してツリーの深さ優先の左から右への走査を開始し、走査をガイドします。トラバーサルがリーフ ノードに到達すると、述語はtrue
. バックトラックでは、バックトラックしてツリー ウォークを続行します。到達可能なリーフ ノードがなくなると、述語は失敗します。
Prolog は記述言語です。述語計算の観点から成功の条件を記述します。次に、Prolog の推論エンジンに適切なソリューションを見つけさせるだけです。私の経験では、手続き的で命令的な思考をモデルに押し込もうとすると、そうでない場合よりも物事が難しくなるだけでなく、パフォーマンスの低下が保証されます。
Leon Sterling と Eliot Shapiro の教科書The Art of Prologは、Clocksin & Mellish のProgramming in Prologよりも非常に価値があり、はるかに有益で啓発的であることがわかりました。

注意して編集:あなたのサンプル述語
pred(X) :-
X = 1 -> do this , ! ; else do that ,
write('x =/= 1')
.
いくつかの問題があります。
まず、C や C#、またはand
andor
演算子の優先順位が異なる他の手続き型言語と同様に、式 like はif ( a && b || c && d ) ...
おそらくあなたが思っているようにはバインドされません。行う:書かれているように、それは次のようにバインドします
pred(X) :-
X=1 ->
( do_this , ! )
;
( do_that , write( 'x =/= 1' ) )
.
あなたがおそらく望んでいたのは
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that ,
) ,
write( 'x =/= 1' )
.
意図したバインディングを明示的にするには、括弧を使用する必要があります。
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that
),
write('x =/= 1')
.
さらに、含意演算子はカットが含まれているかのように機能するため、例のカット(!
)は不要->
です。これ:
foo(X) :-
truthy(X) ->
writeln('truthy!')
;
writeln('falsy')
.
とほとんど同じです
foo(X) :- truthy(X) , ! ,
writeln( 'truthy' ) .
foo(_) :- writeln( 'falsy' ) .
第三に、ヘッド内で統一とパターン マッチングを利用する必要があります。を無視するwrite/1
と、あなたの例は次のように理にかなっているかもしれません
pred(1) :- do_this , ! .
pred(X) :- do_that .
そして、一般的に、プロローグを学んでいるのであれば、一般的に含意演算子 (および代替 (論理 OR, ';'/2
) を避けることをお勧めします。
foo(X) :- ( try_this(X) ; try_that(X) ; finally(X) ) .
好む
foo(X) :- try_this(X) .
foo(X) :- try_that(X) .
foo(X) :- finally(X) .
そして、含意の代わりに:
foo(X) :- X=1 -> try_this(X) ; try_that(X) .
次のようなものを好む:
foo(1) :- ! , try_this(X) .
foo(X) :- try_that(X) .
選択ポイント (およびその排除) が明確になるため、何が起こっているのかを理解しやすくなると思います。