编写一个规则,获取一个列表,其元素本身就是列表,并在每一行打印内部列表的元素:
例子:
?- printList[[1,a],[2,b]])。
1个
2 乙
解决方案如下:
/* BASE CASE: The list is empty, so there is nothing to print */
printList([]).
printList([P|R]):- printList(P),
!,
nl,
printList(R).
printList([X|R]):- write(X),
!,
printList(R).
当列表为空时,我有达到基本情况的 printList 规则,在这种情况下没有可打印的内容。
如果我不在基本情况下(列表不为空),它会调用第二条规则printList([P|R]),现在我有第一个疑问:
元素 P 是一个列表,因为 Prolog 自动将内部列表作为元素处理?
所以,如果我有类似的东西:
[[1,a],[2,b],[3,c],[4,d]]我让 Prolog 以这种方式自动匹配:
P = [1,a](第一个列表作为头元素)
R = [[2,b],[3,c],[4,d]](其他3个列表是尾列表的元素)
然后程序调用printList然后程序在头元素(第一个列表)上
这个解释对吗?
现在我对这个程序的trace有一些疑问,例如如果我执行这个语句,我会得到以下trace:
[trace] ?- printList([[1,a], [2,b]]).
Call: (6) printList([[1, a], [2, b]]) ? creep
Call: (7) printList([1, a]) ? creep
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
Redo: (7) printList([1, a]) ? creep
Call: (8) write(1) ? creep
1
Exit: (8) write(1) ? creep
Call: (8) printList([a]) ? creep
Call: (9) printList(a) ? creep
Fail: (9) printList(a) ? creep
Redo: (8) printList([a]) ? creep
Call: (9) write(a) ? creep
a
Exit: (9) write(a) ? creep
Call: (9) printList([]) ? creep
Exit: (9) printList([]) ? creep
Exit: (8) printList([a]) ? creep
Exit: (7) printList([1, a]) ? creep
Call: (7) nl ? creep
Exit: (7) nl ? creep
Call: (7) printList([[2, b]]) ? creep
Call: (8) printList([2, b]) ? creep
Call: (9) printList(2) ? creep
Fail: (9) printList(2) ? creep
Redo: (8) printList([2, b]) ? creep
Call: (9) write(2) ? creep
2
Exit: (9) write(2) ? creep
Call: (9) printList([b]) ? creep
Call: (10) printList(b) ? creep
Fail: (10) printList(b) ? creep
Redo: (9) printList([b]) ? creep
Call: (10) write(b) ? creep
b
Exit: (10) write(b) ? creep
Call: (10) printList([]) ? creep
Exit: (10) printList([]) ? creep
Exit: (9) printList([b]) ? creep
Exit: (8) printList([2, b]) ? creep
Call: (8) nl ? creep
Exit: (8) nl ? creep
Call: (8) printList([]) ? creep
Exit: (8) printList([]) ? creep
Exit: (7) printList([[2, b]]) ? creep
Exit: (6) printList([[1, a], [2, b]]) ? creep
true.
这对我来说很清楚(我认为我之前的推理是正确的)但是我不明白为什么每当它到达内部列表中的一个元素时,它就会调用它的printList关系(这是一个简单的元素而不是一个列表),例如这里:
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
程序已经考虑了原始列表的第一个列表,然后,必须打印它的第一个元素,为什么要在这个简单元素上调用printList关系
是因为这个简单的元素又可能是内部列表吗?
就像是:
[[[1.1,a1,a2],[1.2,b1,b2]], [2,b]](其中我有一个包含 2 个列表的列表,第一个元素是包含 2 个列表的列表。所以程序检查元素是元素还是内部列表?