Prolog 中的匹配元组
为什么 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 中的列表吗?
Why does Prolog match (X, Xs)
with a tuple containing more elements? An example:
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
Actually this is what I want to achieve but it seems suspicious. Is there any other way to treat a conjunction of terms as a list in Prolog?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
,/2
运算符构建元组 term 在 PROLOG 中通常是右关联的(通常称为序列),因此您的输入a, b(c), d(e(f)), g
实际上很可能是术语(a, (b(c), (d(e(f))), g)))
。您的谓词test2/1
打印了问题中显示的内容,这一事实证明了这一点,在第一次调用test2/1
的第一个子句时,X
匹配a
且Xs
匹配(b(c), (d(e(f)), g))
,然后在第二次调用时X
匹配b(c)
且Xs
匹配(d(e(f)), g)
,等等。如果您确实想处理解释为连词的术语列表,您可以使用以下内容:
...on input
[a, b(c), d(e( f)),g]
。这里的列表结构通常与用,/2
构造的元组解释略有不同(因为,至少在 SWI-PROLOG 中,此类结构是处理用./ 构造的术语的语法糖。 2
的方式与使用,/2
构造序列或元组项的方式大致相同)。这样,如果您可以在代码中允许将列表术语解释为连词,您就可以获得列表术语支持的好处。另一种选择是声明并使用您自己的(可能是中缀运算符)进行连接,例如&/2
,您可以将其声明为:然后您可以构造您的连接作为
a & b(c) & d(e(f)) & g
并从那里适当地处理它,确切地知道&/2
的意思 - 合取。请参阅
op/3
< 的手册页/a> 在 SWI-PROLOG 中了解更多细节 - 如果您不使用 SWI,我认为您使用的任何 PROLOG 实现中都应该有一个类似的谓词 - 如果它值得的话:-)编辑: 要将使用
,/2
构造的元组术语转换为列表,您可以使用如下所示的内容:Tuple term construction with the
,/2
operator is generally right-associative in PROLOG (typically referred to as a sequence), so your input ofa, b(c), d(e(f)), g
might well actually be the term(a, (b(c), (d(e(f)), g)))
. This is evidenced by the fact that your predicatetest2/1
printed what is shown in your question, where on the first invocation of the first clause oftest2/1
,X
matcheda
andXs
matched(b(c), (d(e(f)), g))
, then on the second invocationX
matchedb(c)
andXs
matched(d(e(f)), g)
, and so on.If you really wanted to deal with a list of terms interpreted as a conjunction, you could have used the following:
...on input
[a, b(c), d(e(f)), g]
. The list structure here is generally interpreted a little differently from tuples constructed with,/2
(as, at least in SWI-PROLOG, such structures are syntactic sugar for dealing with terms constructed with./2
in much the same way as you'd construct sequences or tuple terms with,/2
). This way, you get the benefits of the support of list terms, if you can allow list terms to be interpreted as conjunctions in your code. Another alternative is to declare and use your own (perhaps infix operator) for conjunction, such as&/2
, which you could declare as:You could then construct your conjunct as
a & b(c) & d(e(f)) & g
and deal with it appropriately from there, knowing exactly what you mean by&/2
- conjunction.See the manual page for
op/3
in SWI-PROLOG for more details - if you're not using SWI, I presume there should be a similar predicate in whatever PROLOG implementation your'e using -- if it's worth it's salt :-)EDIT: To convert a tuple term constructed using
,/2
to a list, you could use something like the following:嗯...
a, b(c), d(e(f)), g
表示a
和 (b(c)
和(d(e(f))
和g
)),列表[1,2,3]
只是一个[1 | [2 | [3 | []]]]
。即,如果您将该连词转换为列表,您将得到相同的test2([X|Xs]):-...
,但不同之处在于连词携带有关如何组合这两个目标的信息(也可能存在析取(X; Xs)
)。您还可以通过(a, b(c)), (d(e(f)), g) 构建其他连词层次结构。
您可以使用简单的递归类型。在其他语言中,列表也是递归类型,但它们通常假装是数组(具有良好索引的大元组)。
也许你应该使用:
Hmm...
a, b(c), d(e(f)), g
meansa
and (b(c)
and (d(e(f))
andg
)), as well list[1,2,3]
is just a[1 | [2 | [3 | []]]]
. I.e. if you turn that conjuction to a list you'll get the sametest2([X|Xs]):-...
, but difference is that conjunction carries information about how that two goals is combined (there may be disjunction(X; Xs)
as well). And you can construct other hierarchy of conjunctions by(a, b(c)), (d(e(f)), g)
You work with simple recursive types. In other languages lists is also recursive types but they often is pretending to be arrays (big-big tuples with nice indexing).
Probably you should use: