如何理解Prolog中的递归搜索?

如何理解Prolog中的递归搜索?,prolog,program-slicing,failure-slicing,Prolog,Program Slicing,Failure Slicing,下面是一段以递归方式定义数字的Prolog代码: numeral(0). numeral(succ(X)) :- numeral(X). 当给定查询时,数字(X)。Prolog将返回: X = 0 ; X = succ(0) ; X = succ(succ(0)) ; X = succ(succ(succ(0))) ; X = succ(succ(succ(succ(0)))) ; X = succ(succ(succ(succ(su

下面是一段以递归方式定义数字的Prolog代码:

numeral(0). 
numeral(succ(X))  :-  numeral(X).
当给定查询时,数字(X)。Prolog将返回:

X  =  0  ; 

X  =  succ(0)  ; 

X  =  succ(succ(0))  ; 

X  =  succ(succ(succ(0)))  ; 

X  =  succ(succ(succ(succ(0))))  ; 

X  =  succ(succ(succ(succ(succ(0)))))  ; 

X  =  succ(succ(succ(succ(succ(succ(0))))))  ; 

X  =  succ(succ(succ(succ(succ(succ(succ(0)))))))  ; 

X  =  succ(succ(succ(succ(succ(succ(succ(succ(0)))))))) 
yes
根据我所了解的,在执行查询时,prolog将首先将
X
转换为一个类似
(_G42)
的变量,然后搜索事实和规则以找到匹配项

在本例中,它将发现
0
(事实)是正确的匹配项。然后它还将尝试匹配规则。考虑到
\u G42
不是
0
\u G42
是另一个数字的成功。因此,将生成另一个变量(如
\u G44
),
\u G44
将匹配
0
,并且还会进一步类似
\u G42
。由于
\u G44
匹配
0
,因此它将返回到
\u G42
,获得
\u G42=succ(\u G44)=succ(0)

我不确定我的理解是否正确。我画了一张图表来说明我对这个问题的理解。

如果分析是正确的,我仍然觉得很难设计这样的递归函数。由于我是Prolog新手,我想知道这种定义是否总是在应用程序中使用(比如构建专家系统、验证协议),还是只是为了让初学者更好地理解基本的搜索过程?如果经常使用,那么设计这种递归定义的关键点是什么?

我个人的观点:尤其是作为初学者,你没有机会“理解Prolog中的递归搜索”。无数的初学者正试图以这种方式理解Prolog,但他们总是失败

可悲的是,这对工作人员的打击最大:你总是认为你能以某种方式理解它,但最终你无法理解,因为有太多的方法调用最简单的谓词,使用未实例化和(部分)实例化的参数,甚至使用别名变量

您的图表很好地说明了,即使是最简单的递归定义,这样的过程性阅读也会很快变得非常笨拙

理解谓词的一种更容易理解的方法是以声明的方式阅读它:

  • 0
    是一个数字
  • 如果
    X
    是一个数字(无论
    X
    是什么!),那么
    X
    such(X)
    也是一个数字
  • 请注意,
    :-
    偶数表示←,i、 从右到左的含义

    我的建议是把重点放在一个清晰的声明性描述上,说明应该持有什么。为了克服Prolog最初的障碍,您必须放弃这样一种想法,即您可以跟踪CPU执行的步骤,在您当前试图遵循的过程中,这些步骤非常详细。Prolog的级别太高,不适合以这种低级方式进行跟踪。这就像试图通过追踪说话者的神经活动来在法语和英语之间进行口译一样

    写一个清晰的定义,然后将搜索留给Prolog。有许多其他的和有效的方法来理解和分解声明性定义,而不必陷入低级细节。参见示例和。只要您停留在Prolog的所谓纯单调子集中,它们就会工作。专注于这个领域,你将能够取得非常快的进步