Prolog:缺少功能?
Prolog: missing feature?
任何对 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) "binds" 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
在我看来,如果前面的陈述和类似的陈述符合预期,那将非常有用。也就是说,我们需要 link 两个变量,当其中一个绑定到一个值时,另一个会遵循先前建立的规则。
我的问题是:
a) 在 Prolog 中有一些简单的方法可以做到这一点。
b) 如果不可能,是否有任何其他支持此功能的编程语言?
欢迎任何评论。
谢谢大家
* 附录一 *
另一个例子是:
user_id(john,1234).
user_id(tom,5678).
和查询:
X=john,user_id(X,Y).
user_id(X,Y),X=john
目前通过回溯解决。
此主题称为 coroutining, and to be solved in fairly general way - afaik - requires extension to the basic Prolog computation model. Fortunately, most Prologs have such extension... So, let's try in SWISH 以构建您自己的 'reactive' 扩展:
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)).
只要 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.
您可能认为系统会失败,但它会产生一个基本上重述查询的答案。至少答案是正确的,因为它只是说:是的,有一个解决方案 provided 这个关系成立(它不成立,类似于保险合同或保证证书中的细则).
when/2
也称为协程,在许多情况下比 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
任何对 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) "binds" 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
在我看来,如果前面的陈述和类似的陈述符合预期,那将非常有用。也就是说,我们需要 link 两个变量,当其中一个绑定到一个值时,另一个会遵循先前建立的规则。
我的问题是:
a) 在 Prolog 中有一些简单的方法可以做到这一点。
b) 如果不可能,是否有任何其他支持此功能的编程语言?
欢迎任何评论。
谢谢大家
* 附录一 *
另一个例子是:
user_id(john,1234).
user_id(tom,5678).
和查询:
X=john,user_id(X,Y).
user_id(X,Y),X=john
目前通过回溯解决。
此主题称为 coroutining, and to be solved in fairly general way - afaik - requires extension to the basic Prolog computation model. Fortunately, most Prologs have such extension... So, let's try in SWISH 以构建您自己的 'reactive' 扩展:
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)).
只要 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.
您可能认为系统会失败,但它会产生一个基本上重述查询的答案。至少答案是正确的,因为它只是说:是的,有一个解决方案 provided 这个关系成立(它不成立,类似于保险合同或保证证书中的细则).
when/2
也称为协程,在许多情况下比 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