在 Prolog 中获取 "real" prefixes/suffixes/infixes

Get "real" prefixes/suffixes/infixes in Prolog

prefix/suffix 的 Prolog 表示法非常简单: 它几乎将所有工作都放在附加上。 对于那些不知道的人:

prefix(P,L):-append(P,_,L).
suffix(S,L):-append(_,S,L).

现在这意味着 prefix(X,[a,b,c,d]). 的结果 将是:X=[];X=[a];X=[a,b];X=[a,b,c];X=[a,b,c,d]

这是我的问题:我想要一个 "real" 前缀。因此,前缀不能为空,其后的部分也不能为空。 所以查询 prefix(X,[a,b,c,d]). 的结果应该是

X=[a];X=[a,b];X=[a,b,c]

就是这样。

不幸的是,标准内置前缀谓词的真正优点是,它可以使用附加的终止,即append([],Y,Y). 所以很容易知道什么时候停止,一个一个地挑选列表直到列表为空。

我的终止意味着:如果列表中只剩下一个元素,则停止。 我该怎么做?

我天真的结果是:

prefix(P,L):-
length(P,1),append(P,E,L),E/=[].

虽然这感觉不对。我在工作,所以我还没有检查这是否真的有效,但它应该:

有没有更方便的方法呢? 后缀也是如此,这将更加困难,因为您没有办法像头部一样具体地处理尾部,我想我只是颠倒整个事情,然后在其上调用前缀。

中缀只是两个的组合。

希望大家明白我的意思。感谢您的输入! tl;dr: 如何写一个谓词 prefix/2 只过滤真正的前缀,所以前缀本身不能为空,它后面的列表也不能为空。

对于真正的前缀,你可以这样尝试:

list_prefix(List, [H|T]) :-
    append([H|T], [_|_], List).

这只是说第一个参数必须至少有一个元素,列表的其余部分必须至少有一个元素。

并按照@false 的建议使其更明确:

list_real_prefix(List, Prefix) :-
    Prefix = [_|_],
    Rest = [_|_],
    append(Prefix, Rest, List).

"real" 后缀将完全相同:

list_real_suffix(List, Suffix) :-
    Front = [_|_],
    Suffix = [_|_],
    append(Front, Suffix, List).

你也可以为此使用一个 DCG,它是描述性的:

list_prefix(P) --> non_empty_seq(P), non_empty_seq(_).
non_empty_seq([X]) --> [X].
non_empty_seq([X|Xs]) --> [X], non_empty_seq(Xs).

| ?- phrase(list_pref(P), [a,b,c,d]).

P = [a] ? a

P = [a,b]

P = [a,b,c]

no
| ?-

您可以类似地定义后缀:

list_suffix(S) --> non_empty_seq(_), non_empty_seq(S).