列表Prolog列表的第一要素

时间:2019-01-02 18:10:06

标签: prolog

我正在学习Prolog,我看到了这段代码

foo([],[]).
foo([[A,_ ]|L], [A|P]) :-foo(L ,P).

结果表明该代码取列表的N个元素, 广告示例,如果我们给出以下查询:

?foo([[car],[house],[man]],X)
X= [c,h,m]

初读时我发现有问题。 对我来说,这段代码采用list列表的尾部和list的第一个元素的其余部分,因此对我来说,第一个扩展将是(trace)

foo([[house],[man]], ar)
foo([[man]], ouse)
foo([], an)
false.

我尝试使用swi-prolog进行编译并给出以下跟踪信息:

[trace]  ?- trace,foo([[car],[house],[man]],X).
Call: (9) foo([[car], [house], [man]], _1016) ? creep
Fail: (9) foo([[car], [house], [man]], _1016) ? creep
false.

我怎么了?

1 个答案:

答案 0 :(得分:2)

获得第一个元素

您的子句中的模式[A, _]错误,或者至少不够通用[A, _]通过一个包含恰好两个元素的列表来统一,但是对于包含两个以上元素或一个元素的列表(如您所发现的),这将失败。

您需要使用[A|_]模式:确实是列表,其中头是A,而我们对其余的(尾部)不感兴趣。喜欢:

foo([],[]).
foo([[A|_]|L], [A|P]) :- foo(L, P).

话虽如此,您可以通过实现采用列表头的谓词来简化此过程:

head([H|_], H).

,然后使用maplist/3 [swi-doc]

foo(A, B) :-
    maplist(head, A, B).
因此,

maplist将像head那样调用head(Ai, Bi),分别使用AiBi的{​​{1}}和A个元素。

使用第一个字符获取子字符串

但是基于示例输出,这不是您想要的:您还想获取原子的第一个“字符”,我们可以使用string_chars/2 [swi-doc]来做到这一点:

B

,然后再次用maplist/3 [swi-doc]定义head_first([A|_], C) :- string_chars(A, [C|_]).

foo/2

然后我们获得:

foo(A, B) :-
    maplist(head_first, A, B).