まず第一に、dif/2
そして(\==)/2
両方の引数が根拠のある場合、つまり変数がない場合も同じことを意味します。したがって、引数が根拠のあるものになること、またはそれ以上のインスタンス化が結果に影響を与えないように十分にインスタンス化されることを保証できれば(\==)/2
、違いはありません。
node/3
あなたの例では、の答えには常に最初の引数が含まれていることを確認する必要があります。その場合、(\==)/2
プログラムは問題ありません。まれに、dif/2
バージョンよりも効率が悪い場合があります。目標を考えてくださいedge(X, X)
。
多くの場合、(\==)/2
または(\=)/2
ははるかに効率的です。一方、正確性と比較した場合、効率はどれほど重要ですか?
これを確認するもう1つの方法は、2つの側面からの概算として検討(\==)/2
する(\=)/2
ことです。両方が同意した場合にのみ、安全な最終結果が得られます。
歴史的に、dif/2
は最も古い組み込み述語の1つです。dif/2
それは、最初のプロローグであるとしばしば認識される次のバージョンと区別するために、プロローグ0と呼ばれることもある最初のプロローグシステムに存在しました—マルセイユプロローグ—プロローグ1。プロローグがエジンバラにやってきた形。また、dif/2
これは、coroutiningのようなメカニズムを必要とするため、(現在)ISO標準の一部ではありません。そして、多くの(かなり古い)Prologシステムにはそのようなメカニズムがありません。ただし、ISO Prologでも、次のように改善できます。
iso_dif(X, Y) :-
X == Y,
!,
fail.
iso_dif(X, Y) :-
X \= Y,
!.
iso_dif(X, Y) :-
throw(error(instantiation_error,iso_dif/2)).
(これは別の、おそらくより効率的な実装です)
問題のあるケースが、計算全体を停止するエラーによってどのようにカバーされているかに注意してください。
箱から出してすぐにサポートする現在のPrologシステムdif/2
は、B、SICStus、SWI、YAPです。IF、Ciao、XSB、Scryerのライブラリにあります。
この回答も参照してください。
オーバーヘッドに関する私の主張を裏付けるために、同じマシン上のさまざまなPrologでのテストを次に示します。SWIでは10倍のオーバーヘッドがあり、Bではオーバーヘッドはありません。@nfzが指摘しているように、コンパイル時の数値はわずかに異なります。そのため、マイレージは異なる場合があります。
SWI 6.3.4-55
?-1000 = I、time((dif(X、Y)、between(1、I、X)、between(1、I、Y)、false))。
%22,999,020推論、 5.192秒で5.162 CPU(99%CPU、4455477リップ)
false。
?-1000 = I、time((between(1、I、X)、between(1、I、Y)、X \ == Y、false))。
%2,000,001推論、 0.521秒で0.511 CPU(98%CPU、3912566リップ)
false。
B 7.8
| ?-1000 = I、time((dif(X、Y)、between(1、I、X)、between(1、I、Y)、false))。
CPU時間0.364秒。
いいえ
| ?-1000 = I、time((between(1、I、X)、between(1、I、Y)、X \ == Y、false))。
CPU時間0.356秒。
いいえ
YAP
?-1000 = I、time((dif(X、Y)、between(1、I、X)、between(1、I、Y)、false))。
2.566秒で%2.528 CPU(98%CPU)
いいえ
?-1000 = I、time((between(1、I、X)、between(1、I、Y)、X \ == Y、false))。
0.963秒で%0.929 CPU(96%CPU)
いいえ