规则的意外结果

Unexpected result of the rule

我尝试编写一个规则来检查列表是否是一个链,例如:
[[5,2],[2,4]] - 真
[[7,2],[4,0]] - 错误
[[1,2]] - 错误,单元素列表也不是链。

因此,模式就像 [[a,b], [b,c], [c,d], ...](内部列表总是包含两个元素,并且 a、b、c、d... 中的任何一个都可能相等)。

chain([]):-!.
chain([X]):-false.
chain([_|[]]):-!.
chain([[_, X2]|[[Y1, Y2]|Tail]]):-
    X2 == Y1,
    chain([[Y1, Y2]|Tail]).

-? chain([[1,2]]).我是真的,这让我很困惑。

我也尝试用chain(L):-length(L, Len),Len>1.替换第二行,但结果还是一样。

感谢任何帮助和解释。

不需要显式失败。只是不要为这种情况编写规则,规则将失败,因为它无法成功。

这是一种方法:

chain([[_,X],[X,Y]|Rest]) :-
    chain_1(Rest, Y).

chain_1([], _).
chain_1([[X,Y]|Rest], X) :-
    chain_1(Rest, Y).

这适用于所有极端情况吗?


这里没什么好解释的。如果有什么不明显的地方,请提出具体问题。

因为对围绕这些部分的最笼统的查询有一定的痴迷,我是一个天生的讨好者,我会入乡随俗:

?- chain(X).
X = [[_, _A], [_A, _]] ;
X = [[_, _A], [_A, _B], [_B, _]] ;
X = [[_, _A], [_A, _B], [_B, _C], [_C, _]] ;
X = [[_, _A], [_A, _B], [_B, _C], [_C, _D], [_D, _]] .

酷!

因为 chain_1/2 是列表中的左折,你可以这样写:

chain([[_,X],[X,Y]|Rest]) :-
    foldl(chain_rule, Rest, Y, _).

chain_rule([X,Y], X, Y).

不会变得更具可读性,但您可以向您的朋友炫耀。