首先,当两个论点都成立时dif/2
,(\==)/2
意思相同,即自由变量。因此,如果您可以确保论点是有根据的——或者更确切地说是充分实例化,使得进一步的实例化不会影响结果(\==)/2
——那么它就不会产生影响。
在您的示例中,我们需要确定答案node/3
总是包含一个基本的第一个论点。在这种情况下,(\==)/2
程序很好。在极少数情况下,它的效率可能低于该dif/2
版本。想想目标edge(X, X)
。
在许多情况下,(\==)/2
或什至(\=)/2
明显更有效。另一方面,与正确性相比,效率有多重要?
看待这一点的另一种方式是从两个方面考虑(\==)/2
和(\=)/2
作为近似值:只有当双方都同意时,我们才会有一个安全的最终结果。
从历史上看,dif/2
它是最古老的内置谓词之一。它出现在第一个 Prolog 系统中,有时称为 Prolog 0,以将其与下一个版本区分开来,后者通常被认为是第一个 Prolog——Marseille Prolog——Prolog 1。Prolog 1 不再有dif/2
,它在这个Prolog 来到爱丁堡的形状。此外,dif/2
它不是 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)).
(这是另一个可能更有效的实现)
请注意有问题的情况如何被停止整个计算的错误所覆盖。
当前支持dif/2
开箱即用的 Prolog 系统有 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.162 CPU在 5.192 秒内(99% CPU,4455477 唇)
错误的。
?- 1000=I,time(( 介于(1,I,X),介于(1,I,Y), X \== Y, false ))。
% 2,000,001 推理,0.511 CPU在 0.521 秒内(98% CPU,3912566 唇)
错误的。
乙 7.8
| ?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false ))。
CPU时间0.364秒。
不
| ?- 1000=I,time(( 介于(1,I,X),介于(1,I,Y), X \== Y, false ))。
CPU时间0.356秒。
不
雅普
?- 1000=I,time(( dif(X,Y), between(1,I,X), between(1,I,Y), false ))。
% 2.528 CPU在 2.566 秒 ( 98% CPU)
不
?- 1000=I,time(( 介于(1,I,X),介于(1,I,Y), X \== Y, false ))。
% 0.929 CPU在 0.963 秒内 (96% CPU)
不