任何在Prolog有一定经验的程序员都知道使用一元符号表示数字的优点。例如,如果我们将数字表示为1“(”4“是列表”[1,1,1,1]“等等)的列表,我们可以定义:
unary_succ(X,[1|X]).
以下查询执行预期的操作:
?- X=[1,1],unary_succ(X,Y).
X = [1, 1],
Y = [1, 1, 1].
?- unary_succ(X,Y),X=[1,1].
X = [1, 1],
Y = [1, 1, 1].
?- unary_succ(X,Y),Y=[1,1].
X = [1],
Y = [1, 1].
通过这种方式,语句unary_succ(X,Y)以一种方式“绑定”X和Y,如果在声明事实之后,其中一个变量绑定到一个值,另一个变量绑定到。
但是,如果我们使用内部数字表示,则无法执行此操作:
?- X=2,succ(X,Y).
X = 2,
Y = 3.
?- succ(X,Y),X=2.
ERROR: succ/2: Arguments are not sufficiently instantiated
?- succ(X,Y),Y=2.
ERROR: succ/2: Arguments are not sufficiently instantiated
在我看来,先前的陈述和类似的陈述能够达到预期目标是非常有用的。也就是说,我们需要链接两个变量,当其中一个变量绑定到一个值时,另一个变量遵循先前建立的规则。
我的问题是:
a)在Prolog中做一些简单的方法。
b)如果不可能,任何其他支持此功能的编程语言?
欢迎任何评论。
感谢大家。
*附录I *
另一个例子是:
user_id(john,1234).
user_id(tom,5678).
和查询:
X=john,user_id(X,Y).
user_id(X,Y),X=john
目前通过回溯来解决。
答案 0 :(得分:4)
只要Prolog系统的答案仅限于(句法)答案替换,您描述的问题就存在。在您的示例中,目标succ(X, Y)
将需要无限多个答案来描述整套解决方案。因此,会发出instantiation_error
。
要解决这个问题,我们需要扩展答案。所以答案不仅包括答案替换,还包括一些更精细的方式来描述一些集合。
library(clpfd)
提供对Z(以及最显着的有限域)的约束。
?- use_module(library(clpfd)).
?- Y #= X+1.
X+1#=Y.
请注意,对于一般情况,此类解算器不是很强大:
?- Y #= X+1, X #= Y+1.
Y+1#=X,
X+1#=Y.
您可能希望系统失败,但它会产生一个基本上重述查询的答案。至少答案是不正确的,因为它只是说明:是的,有一个解决方案提供这种关系成立(它没有,类似于保险合同或担保证书中的细则)。 / p>
when/2
也称为coroutining,在许多情况下比clpfd
更弱。但是,在少数情况下,clpfd
的某些实现更强。考虑dif/2
,可以表示为when(?=(X,Y), X \== Y)
和
| ?- dif(X, Y), X = Y.
no
...而(在SICStus中)
| ?- X #\= Y, X #= Y.
Y #= X,
Y #\= X,
Y in inf..sup,
X in inf..sup ? ;
no
library(clpq)
提供的解算器在许多情况下更强,但缺少整数特定约束,如mod/2
。在许多情况下,使用它仍然很有趣,如SICStus中所示:
| ?- use_module(library(clpq)).
yes
| ?- {Y=X+1}.
{X = -1+Y} ?
yes
| ?- {Y=X+1}, {X=Y+1}.
no
答案 1 :(得分:3)
这个主题被称为coroutining,并且要以相当一般的方式解决 - afaik - 需要扩展到基本的Prolog计算模型。幸运的是,大多数Prolog都有这样的扩展......所以,让我们尝试in SWISH来构建你自己的“反应性”'扩展:
my_succ(X, Y) :- when((nonvar(X);nonvar(Y)), succ(X, Y)).
编辑并非完全没有意义,但Jan在SWI-Prolog邮件列表上发布了一个关于协同应用程序的简单示例:
?- freeze(X, writeln(X)), findall(X, between(1,3,X), Xs).
1
2
3
Xs = [1, 2, 3],
freeze(X, writeln(X)).