生成从0到9的数字(Prolog)

生成从0到9的数字(Prolog),prolog,Prolog,我正在读一个解代数图程序的源代码。它的一部分是一个测试从0到9的每个数字的过程。这是它的源代码: digit(0, 0) :- !. digit(X, X). digit(D, N) :- N2 is N - 1 , digit(D, N2) . 当我运行此命令并询问时,我得到: ?- digit(X, 9). X = 9 ; X = 8 ; X = 7 ; X = 6 ; X = 5 ; X = 4 ; X = 3 ; X = 2 ; X = 1 ; X = 0. 我似乎不太明白为

我正在读一个解代数图程序的源代码。它的一部分是一个测试从0到9的每个数字的过程。这是它的源代码:

digit(0, 0) :- !.
digit(X, X).
digit(D, N) :-
  N2 is N - 1 ,
  digit(D, N2) .
当我运行此命令并询问时,我得到:

?- digit(X, 9).
X = 9 ;
X = 8 ;
X = 7 ;
X = 6 ;
X = 5 ;
X = 4 ;
X = 3 ;
X = 2 ;
X = 1 ;
X = 0.
我似乎不太明白为什么程序数字会这样做。谁能给我解释一下吗


谢谢你的回答

首先,一些术语<代码>数字在Prolog中被称为“谓词”,而不是“过程”或“函数”。这一点很重要,因为“谓词”并不完全执行函数或过程所执行的操作。谓词是对逻辑关系的描述,调用谓词试图满足该关系定义的逻辑目标,该目标可能有零个、一个或多个解决方案。为了满足这个目标,它可以实例化任何未实例化的变量或术语(那些尚未赋值的)

要理解
数字的行为
,您需要通过理解谓词的作用来“阅读”它。在此上下文中,
数字(X,N)
的含义是“X是0到N范围内的数字”。如果
N
为0,那么根据该定义,
X
只能得到一个答案(0)。如果
N>0
,那么我们希望有多个答案,这将使
数字(X,N)
为真。为此编写的规则(谓词)包括:

digit(0, 0) :- !.
digit(X, X).
digit(X, N) :- N2 is N - 1, digit(X, N2).
这里的顺序很重要,因为Prolog将尝试按照给定的顺序匹配这些规则,如下所述

首先宣布的事实是:

digit(0, 0) :- !.
这表示0是介于0和0之间的唯一数字。我之所以这么说,是因为削减将告诉Prolog,在实现这一目标后,不要再寻找任何答案。因此
数字(0,0)
将为真,目标
数字(X,0)。
将产生
X=0
并完成

接下来是:

digit(X, X).
这表明
X
是从0到
X
的有效数字。没有削减,因此在满足此规则后,可能会寻求后续解决方案。像
数字(X,9)
这样的目标将匹配此规则,并产生
X=9
。请注意,当您键入
数字(X,9)
时,第一个找到的结果是
X=9
,因为这是遇到的第一个满足
数字(X,9)
要求目标的规则

最后,还有:

digit(X, N) :- N2 is N - 1, digit(X, N2).
这表示
X
是从0到
N
的数字,如果
X
是从
0到
N-1的数字(
N2
用于实例化值
N-1
)。因此,如果我输入一个目标
数字(X,9)
,它首先满足
数字(X,X)
,如上所述。然后,由于该规则中没有切入点,当Prolog回溯更多解决方案时,它已经满足了
数字(X,X)
,因此将继续满足
数字(X,9)
,并在这个过程中,尝试满足
数字(X,8)
,如
数字(X,N)
规则所述。由于这是一个新的目标(而不是原来的
数字(X,9)
目标),它从顶部开始,按照相同的逻辑,将首先遇到
数字(X,X)
,并由
X=8
满足。因此,显示的第二个解决方案将是
X=8
(请记住,给出的第一个解决方案是
X=9

此逻辑按顺序继续,满足
数字(X,7)
数字(X,6)
等,显示
X=7
X=6
等的解决方案,直到最终达到
数字(X,0)
。如上所述,
数字(X,0)
最终将由
数字(0,0)
满足,产生解决方案
X=0
,然后由于切割而完成。在这一点上,它已经用尽了所有的解决方案和完成

因此,结果是
X=9
X=8
,…,
X=0

这一点的关键是Prolog继续(迭代/回溯)为您指定的目标找到解决方案,找到所有可能的解决方案,直到它找到所有的可能性(由书面规则作为谓词建立),或者直到这些可能性被使用cut截断