我已经设法回答了我自己的问题,但不是纯粹的解决方案。
一些观察
当一个列表的长度已知时,编写一个计划执行某个目标的程序遇到的困难是实际条件可能会改变。考虑一下:
when(fixed_length(L), Goal)
L
如果未绑定或最后一个尾部未绑定,则列表的长度可能会更改。假设我们有这个论点L = [_,_|Tail]
。L
仅当具有固定宽度时才Tail
具有固定宽度(换句话说,L
如果T
是列表,则为列表)。因此,检查的条件Tail
可能是一开始唯一要做的事情。但是 ifTail
成为[a|Tail2]
一个新的 when 条件来测试是否Tail2
是一个列表是需要的。
解决方案
1.获取when-condition
我已经实现了一个谓词,它将一个部分列表与当它可能成为一个列表时发出信号的 when 条件(即最深的尾部nonvar(T)
在哪里)。T
condition_fixed_length(List, Cond):-
\+ (List = []),
\+ \+ (List = [_|_]),
List = [_|Tail],
condition_fixed_length(Tail, Cond).
condition_fixed_length(List, Cond):-
\+ \+ (List = []),
\+ \+ (List = [_|_]),
Cond = nonvar(List).
2.递归的when-conditioning
check_on_fixed_length(List, Goal):-
(
condition_fixed_length(List, Condition)
->
when(Condition, check_on_fixed_length(List, Goal))
;
call(Goal)
).
示例查询
假设我们要检查 的所有元素L
是否a
在 的大小L
固定时:
?- check_on_fixed_length(L, maplist(=(a), L)).
when(nonvar(L), check_on_fixed_length(L, maplist(=(a), L))).
...然后L = [_,_|Tail]
:
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1].
L = [_G2887, _G2890|L1],
when(nonvar(L1), check_on_fixed_length([_G2887, _G2890|L1], maplist(=(a), [_G2887, _G2890|L1]))).
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1], length(L1, 3).
L = [a, a, a, a, a],
L1 = [a, a, a].
不纯
conditon_fixed_length/2
是杂质的来源,从以下查询可以看出:
?- L = [X, Y|Tail], condition_fixed_length(L, Cond), L = [a,a].
L = [a, a],
X = Y, Y = a,
Tail = [],
Cond = nonvar([]).
?- L = [X, Y|Tail], L = [a, a], condition_fixed_length(L, Cond).
false.