我正在学习 Prolog,我看到了这段代码
foo([],[]).
foo([[A,_ ]|L], [A|P]) :-foo(L ,P).
Run Code Online (Sandbox Code Playgroud)
结果表明,此代码获取列表列表中的 N 个元素,如果我们给出以下查询,则举个例子:
?foo([[car],[house],[man]],X)
X= [c,h,m]
Run Code Online (Sandbox Code Playgroud)
初读时我发现有些不对劲。对我来说,这段代码采用列表列表的尾部和列表第一个元素的其余部分,所以对我来说,第一次扩展将是(跟踪)
foo([[house],[man]], ar)
foo([[man]], ouse)
foo([], an)
false.
Run Code Online (Sandbox Code Playgroud)
我尝试使用 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.
Run Code Online (Sandbox Code Playgroud)
我有什么错吗?
您的子句中的模式[A, _]是错误的,或者至少不够通用。与仅包含两个[A, _]元素的列表相结合,但是对于具有两个以上元素或一个元素的列表,这将失败,就像您发现的那样。
您需要使用该[A|_]模式:确实是一个列表,其中头部是A,我们对其余部分(尾部)不感兴趣。喜欢:
foo([],[]).
foo([[A|_]|L], [A|P]) :- foo(L, P).Run Code Online (Sandbox Code Playgroud)
话虽如此,您可以通过实现一个采用列表头部的谓词来简化这一点:
head([H|_], H).
Run Code Online (Sandbox Code Playgroud)
然后使用maplist/3[swi-doc]:
foo(A, B) :-
maplist(head, A, B).Run Code Online (Sandbox Code Playgroud)
maplist因此将分别调用like head、和的元素。head(Ai, Bi)AiBiAB
但根据示例输出,这不是您想要的:您还想获得原子的第一个“字符”,我们可以通过使用string_chars/2[swi-doc]来做到这一点:
head_first([A|_], C) :-
string_chars(A, [C|_]).Run Code Online (Sandbox Code Playgroud)
然后foo/2用maplist/3[swi-doc]再次定义:
foo(A, B) :-
maplist(head_first, A, B).Run Code Online (Sandbox Code Playgroud)
然后我们得到:
?- foo([[car],[house],[man]], X).
X = [c, h, m].
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16490 次 |
| 最近记录: |