4

为什么 Prolog 匹配(X, Xs)包含更多元素的元组?一个例子:

test2((X, Xs)) :- write(X), nl, test2(Xs).                                    
test2((X)) :- write(X), nl.                                                   
                                                                              
test :-                                                                       
        read(W),                                                               
        test2(W). 

?- test.
|: a, b(c), d(e(f)), g.
a
b(c)
d(e(f))
g
yes

实际上这是我想要实现的目标,但似乎很可疑。有没有其他方法可以将术语的连词视为 Prolog 中的列表?

4

2 回答 2

4

使用运算符的元组构造,/2在 PROLOG 中通常是右关联的(通常称为sequence),因此您的输入a, b(c), d(e(f)), g很可能实际上是 term (a, (b(c), (d(e(f)), g)))。事实证明,您的谓词test2/1 打印了您的问题中显示的内容,第一次调用test2/1,X匹配aXs匹配的第一个子句的位置(b(c), (d(e(f)), g)),然后在第二次调用X匹配b(c)Xs匹配(d(e(f)), g)的位置,依此类推。

如果您真的想处理解释为连词的术语列表,您可以使用以下内容:

test2([X|Xs]) :- write(X), nl, test2(Xs).                                    
test2([]).

...关于输入[a, b(c), d(e(f)), g]。这里的列表结构通常与用构造的元组略有不同,/2(至少在 SWI-PROLOG 中,这样的结构是句法糖,用于处理用构造的./2术语与构造序列或元组术语的方式大致相同,/2)。这样,如果您可以允许将列表项解释为代码中的连词,您就可以从支持列表项的好处中受益。另一种选择是声明并使用您自己的(可能是中缀运算符)进行连接,例如&/2,您可以将其声明为:

:- op(500, yfx, &). % conjunction constructor

然后,您可以构建您的合取a & b(c) & d(e(f)) & g并从那里适当地处理它,确切地知道您的意思&/2- 合取。

有关更多详细信息,请参阅op/3SWI-PROLOG 中的手册页 - 如果您不使用 SWI,我认为在您使用的任何 PROLOG 实现中都应该有一个类似的谓词 - 如果值得加盐:-)

编辑:要将使用构造的元组术语转换,/2为列表,您可以使用以下内容:

conjunct_to_list((A,B), L) :-
  !,
  conjunct_to_list(A, L0),
  conjunct_to_list(B, L1),
  append(L0, L1, L).
conjunct_to_list(A, [A]).
于 2010-05-24T00:28:40.773 回答
0

嗯...a, b(c), d(e(f)), g表示aand ( b(c)and ( d(e(f))and g)),以及 list[1,2,3]只是一个[1 | [2 | [3 | []]]]. 即,如果您将该连词转换为列表,您将得到相同的test2([X|Xs]):-...结果,但不同之处在于连词携带有关这两个目标如何组合的信息(也可能存在分离(X; Xs))。您可以通过以下方式构建其他连词层次结构(a, b(c)), (d(e(f)), g)

您使用简单的递归类型。在其他语言中,列表也是递归类型,但它们通常伪装成数组(具有良好索引的大元组)。

可能你应该使用:

test2((X, Y)):- test2(X), nl, test2(Y).
test2((X; Y)). % TODO: handle disjunction
test2(X) :- write(X), nl.
于 2010-05-23T22:55:43.387 回答