Prolog return 值比较

Prolog return value comparation

我正在学习逻辑编程的基础知识。 我解决了一些练习,现在我在创建一个带有两个参数的函数时遇到了麻烦,一个非空列表的列表,其元素连接在一起形成第二个参数。

当我创建一个连接列表列表元素的函数时:

concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!.

现在,我需要知道的是如何获取该函数的 return 值并将其与列表(函数的第二个参数)进行比较。

Prolog 没有过程编程语言意义上的函数或 return 值。它有 断言关系的断言 。它有术语,其中包括 variables,其中有一些限制:

  • 所有变量都是局部变量,并且
  • 一个变量,一旦赋值,就不再是变量。这就是为什么它被称为统一

所以....

如果您想要一个将接受两个列表并产生它们的串联的谓词,您需要将第三个变量传递给它。您可以这样调用它:

concat([a,b],[c,d],X).

断言 X[a,b][c,d] 的串联。 Prolog 的推理引擎随后将评估断言的真假。

大多数递归问题都有一些特殊情况和更一般的情况。这种 concat/3 谓词的实现可能看起来像这样(注释以解释它在做什么)。

  • 首先,我们有一个特殊(且终止)的情况:如果左侧列表为空,则连接只是右侧列表。

    concat( [] , Bs , Bs ).

  • 接下来,我们有一个一般情况:如果左侧列表非空,我们需要将它添加到我们正在构建的连接中(然后向下递归。)

    concat( [A|As] , Bs , [A|Cs] ) :- concat(As,Bs,Cs).

只有两个。您还会注意到它是双向的:它也很乐意将列表分开。像这样调用它:

concat( Prefix , Suffix,  [a,b,c,d] ).

将在回溯时生成所有可能的方式 [a,b,c,d] 可以拆分为前缀和后缀:

Prefix    Suffix
--------- ---------
[]        [a,b,c,d]
[a]       [b,c,d]
[a,b]     [c,d]
[a,b,c]   [d]
[a,b,c,d] []

这是一种允许子列表中的单个元素的方法,但不允许空子列表:

concat([[L]], [L]).
concat([[H],L|T], [H|R]) :- concat([L|T], R).
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT).

这里避免空列表的方法是在递归子句中调出两个头元素,在基本情况中调出一个单独的元素列表。这可以防止空子列表成功,正如原始 post.

的评论中所要求的那样

如果你有一个已经实例化的变量Y,你想知道它是否是连接列表列表LL的结果,你只需查询:

concat(LL, Y).

如果 Y 是列表 LL 的串联,这将是 true,如果不是,则为 false。您不必 "return and compare"(例如,在 C 中,您可能会说 concat(LL) == Yconcat(LL, X); if (X == Y)...)。这是因为 concat 是定义在两个参数之间的 关系 并且它确定是否可以按照规定的规则(谓词的子句)进行查询 true ).

如果你已经得到一个结果,想确定它是否可以统一到另一个变量,Z,那么你可以说:

concat(X, Y), Y = Z.

注意,在Prolog中,concat(X, Y) == Z判断谓词的结果是否等于Z是不正确的,因为它不是returns一个值的函数。

您只需要基本案例

concat([],[]).
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3).

它也适用于空(子)列表。 我已经删除了无用的剪辑。