只是补充两个已经很好的答案......
在 Prolog 中,您不会将事物视为具有参数输入和输出的“函数”(尽管它们确实如此),而是将其视为定义规则并尝试实例化任何变量参数(未实例化的变量)的“谓词”这样的方式,使规则是真实的。这个过程可能会导致没有解决方案、一个解决方案或多个解决方案,而您将获得所有解决方案。并非所有谓词都为未实例化变量的每个组合提供这种“完整功能”,或者如果有太多变量未实例化,则提供解决方案在逻辑上变得不切实际。在任何这些情况下决定参数的行为,以及谓词是否有任何解决方案,是谓词的逻辑,而不是输入或输出的任何正式声明。
让我们以给定concatenate
的为例(注意我使用的是 GNU Prolog)。谓词的concatenate(L1, L2, L3)
意思是“L1 与 L2 连接(按该顺序)给出 L3”,这比说“给定 L1 和 L2,在 L3 中提供它们的连接”更笼统,这意味着特定的输入和输出。
所以如果我输入:
concatenate( [1,2], [3,4], L3 ).
我得到:
L3 = [1,2,3,4]
(1 ms) yes
| ?-
这意味着 prolog 找到了一种解决谓词的方法,其中显示了L3
. 我也可以输入这个:
concatenate( L1, [3,4], [1,2,3,4] ).
我会得到:
L1 = [1,2]
(1 ms) yes
| ?-
这意味着 prolog 找到了一种解决谓词的方法,其中显示了L1
. 同样,如果我进入concatenate( [1,2], L2, [1,2,3,4] )
,我会得到一个解决方案:L2 = [3,4]
.
让我们尝试一些更有趣的事情:
concatenate( L1, L2, [1,2,3,4] ).
Prolog 会为此找到解决方案,但我提供了两个未实例化的变量。因此,解决方案将涉及以下可能性:
L1 = [1,2,3,4]
L2 = [] ? ;
L1 = [1,2,3]
L2 = [4] ? ;
L1 = [1,2]
L2 = [3,4] ? ;
L1 = [1]
L2 = [2,3,4] ? ;
L1 = []
L1 = [1,2,3,4] ? ;
(1 ms) yes
| ?-
现在让我们试试这个:
concatenate( [1,2], L2, L3 ).
我得到:
L3 = [1,2|L2]
| ?-
L2
在这种情况下,并且因此的可能性L3
是无限的,因此 prolog 显示了一个通用解决方案。
在您的示例中,concatenate( X, [2,Y], [1,1,1,2,3] )
同样的想法也适用。Prolog 将尝试找到满足“与 [2,Y] 连接的 X 给出 [1,1,1,2,3]”条件的 和 的实例化,并且 [2,Y] 是具有第一个元素X
和第二个元素的列表元素。在这种情况下,只有您展示的一种解决方案。Y
2
Y
作为这个主题的变体,使用@DrH 描述的列表概念,如果你这样做了:
concatenate( X, [2|Y], [1,1,1,2,3] ).
你会得到X = [1,1,1]
和Y = [3]
。请注意,如果您这样做:
concatenate( X, [2,Y], [1,1,1,2,3,4] ).
你得到'no'(没有解决方案),因为Y
这里显示为一个原子,而不是一个列表(因为逗号语法)。换句话说,没有两个元素列表看起来像[2,Y]
which,当与任何可能性连接时,X
将 yield [1,1,1,2,3,4]
。但如果你这样做:
concatenate( X, [2|Y], [1,1,1,2,3,4] ).
你会得到X = [1,1,1]
,Y = [3,4]
因为现在我将未实例化的内容显示Y
为列表的尾部,它本身就是一个列表,而不仅仅是一个原子(使用|
语法)。
正如@WillNess 指出的那样,如果您未实例化某些变量,给定谓词的文档将告诉您希望该谓词的行为。一个写得很好的序言谓词比一个写得不好或限制性更强的谓词更有可能“做你期望或想要的”。这不会使更受限制的谓词“坏”,因为它可能会起到非常有用的作用。它不会那么有用。在编写自己的序言谓词时,您会考虑这些事情。
Prolog 就像围棋游戏:一些简单的规则,但有许多有趣的可能性。