这里提供了另一种定义这样一个谓词的可能性。每当您描述列表时,考虑使用DCG是值得的,因为它们产生易于阅读的代码。首先让我们观察到只需要三个参数,即列表、要插入的元素和已在所需位置插入元素的列表。参数P和C仅用于簿记目的,因此将它们隐藏在谓词内部是适当的。既然我们已经重新设计了谓词接口,那么让我们也给它一个更具描述性的名称,反映其关系特性,比如说list_e_inserted/3:
list_e_inserted(L,E,I) :-
phrase(inserted(L,E,1,1),I).
inserted([],_E,_P,_C) -->
[].
inserted([H|T],E,P,P) -->
{P1 is P*2, C1 is P+1},
[H,E],
inserted(T,E,P1,C1).
inserted([H|T],E,P,C) -->
{dif(P,C), C1 is C+1},
[H],
inserted(T,E,P,C1).
现在让我们来看一下谓词是如何工作的:
?- list_e_inserted([],10,I).
I = [].
?- list_e_inserted([1],10,I).
I = [1, 10] ;
false.
?- list_e_inserted([1,2],10,I).
I = [1, 10, 2, 10] ;
false.
?- list_e_inserted([1,2,3],10,I).
I = [1, 10, 2, 10, 3] ;
false.
?- list_e_inserted([1,2,3,4],10,I).
I = [1, 10, 2, 10, 3, 4, 10] ;
false.
谓词也可以反向工作:
?- list_e_inserted(L,E,[1,10,2,10,3,4,10,5]).
L = [1, 2, 3, 4, 5],
E = 10 ;
false.
最常见的查询也可以得到所需的解决方案:
?- list_e_inserted(L,E,I).
L = I, I = [] ;
L = [_G23],
I = [_G23, E] ;
L = [_G23, _G35],
I = [_G23, E, _G35, E] ;
L = [_G23, _G35, _G47],
I = [_G23, E, _G35, E, _G47] ;
L = [_G23, _G35, _G47, _G53],
I = [_G23, E, _G35, E, _G47, _G53, E] ;
.
.
.