此代码需要一些更改。
我们如何关联“输入列表”和“输出列表”来满足规范?
我们很幸运,因为规范允许我们将“输入列表”(左)和“输出列表”(右)中的元素一对一关联,因此:
sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
relate_element(LeftHead, RightHead),
relate_lists(LeftTail, RightTail).
关联没有当前头的尾部与关联任何列表相同,因此:
sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
relate_element(LeftHead, RightHead),
sublist(LeftTail, RightTail).
左侧的空列表与右侧的空列表相关,因此基本情况是(正确):
sublist([], []).
基本情况不能与“正常”情况混淆,因为头部 sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :- 中的参数与空列表不匹配,因此无需在基本和常规的子句主体中添加任何额外检查将它们分开。不错。
现在,relate_element(LeftHead, RightHead) 呢?
让我们编程出relate_element(LeftHead, RightHead) :- ....。
规范说“左头”的形式是(X,Y,Z)(这是不好的形式,最好是[X,Y,Z],但让那只狗躺着吧)。
所以我们只对匹配 LeftHead 的调用感兴趣:
relate_element((X,Y,Z), RightHead) :- ...
规范说RightHead 应该只是Y。好的!
relate_element((X,Y,Z), Y) :- ...
当获得与头参数匹配时,正文中会发生什么?好吧,没什么,只是成功。
relate_element((X,Y,Z), Y) :- true.
简化为
relate_element((X,Y,Z), Y).
我们的计划:
sublist([], []).
sublist( [ LeftHead | LeftTail ] , [ RightHead | RightTail ] ) :-
relate_element(LeftHead, RightHead),
sublist(LeftTail, RightTail).
relate_element((X,Y,Z), Y).
但您也可以声明LeftHead 从一开始就必须是(X,Y,Z),类似于RightHead 是Y。因此
sublist([], []).
sublist( [ (X,Y,Z) | LeftTail ] , [ Y | RightTail ] ) :-
relate_element((X,Y,Z), Y),
sublist(LeftTail, RightTail).
relate_element((X,Y,Z), Y).
relate_element/2 现在什么都不做,所以让我们简化(并用_ 标记单例变量):
sublist([], []).
sublist( [ (_X,Y,_Z) | LeftTail ] , [ Y | RightTail ] ) :-
sublist(LeftTail, RightTail).
有效吗?以plunit为例,我们来看看正确的事情是否确实相关,而错误的事情是否不相关:
:- begin_tests(sublist).
test(one) :- sublist([],[]).
test(two) :- sublist([(a,b,c),(e,f,g),(h,i,j)],[b,f,i]).
test(three,fail) :- sublist([(a,b,c),(1,2),(h,i,j)],_).
test(four,fail) :- sublist([(a,b,c),(e,f,g),(h,i,j)],[b,x,i]).
test(five,fail) :- sublist([(a,b,c),(e,f,g),(h,i,j)],[]).
:- end_tests(sublist).
rt(sublist) :- run_tests(sublist).
然后
?- rt(_X).
% PL-Unit: sublist ..... done
% All 5 tests passed
_X = sublist.
您也可以测试谓词是否“向后”工作。确实如此,为输入发出“模板”:
?- sublist(X,[b,f,i]).
X = [(_10626, b, _10634), (_10644, f, _10652), (_10662, i, _10670)].