问题
有没有可能在列表的长度已知/固定后立即安排执行目标,或者,正如@false在评论中指出的那样,给定的参数变成了[正确]列表?沿着这条线:
when(fixed_length(L), ... some goal ...).
当条件可以仅使用?=/2
、nonvar/1
、ground/1
、,/2
和;/2
来构造时,并且当查看整个列表时,它们似乎不是很有用。
作为进一步的细节,如果可能的话,我正在寻找一种呈现逻辑纯度的解决方案。
动机
我认为,如果希望使用谓词p(L)
来检查列表L
的属性,但不以生成的方式使用它,则此条件可能很有用。
例如,如果L
具有固定长度(即,L
是列表(,则[出于效率或终止原因]优选按此顺序执行以下连词p1(L), p2(L)
,否则按相反顺序执行p2(L), p1(L)
(如果L
是部分列表(。
这可能是这样实现的:
when(fixed_length(L), p1(L)), p2(L).
更新
我确实实现了一个解决方案,但它缺乏纯粹性。
如果when/2
支持条件list/1
,那就太好了。同时,考虑:
list_ltruth(L, Bool) :-
freeze(L, nvlist_ltruth(L, Bool)).
nvlist_ltruth(Xs0, Bool) :-
( Xs0 == [] -> Bool = true
; Xs0 = [_|Xs1] -> freeze(Xs1, nvist_ltruth(Xs1, Bool))
; Bool = false
).
when_list(L, Goal_0) :-
nvlist_ltruth(L, Bool),
when(nonvar(Bool),( Bool == true, Goal_0 )).
所以你也可以把它和其他条件结合起来。
如果L
不是列表,则可能会产生类型错误。
when(nonvar(Bool), ( Bool == true -> Goal_0 ; sort([], L) ).
以上技巧仅适用于符合ISO的Prolog系统,如SICStus或GNU,该系统为sort([],[a|nonlist])
生成type_error(list,[a|nonlist])
,否则将其替换为:
when(nonvar(Bool),
( Bool == true -> Goal_0 ; throw(error(type_error(list,L), _)).
许多系统都包含一些特定于实现的内置功能,如'$skip_list'
,可以快速遍历列表,您可能需要在此处使用它。
我已经设法回答了自己的问题,但不是用一个纯粹的解决方案。
一些观察结果
当列表的长度精确已知时,编写一个计划执行某个目标的程序所遇到的困难是实际条件可能会改变。考虑一下:
when(fixed_length(L), Goal)
如果L
未绑定,或者最后一个尾部未绑定,则列表的长度可能会更改。假设我们有这个论点L = [_,_|Tail]
。只有当Tail
具有固定宽度时,L
才具有固定宽度(换句话说,如果T
是列表,则L
是列表(。因此,检查Tail
的条件可能是最初唯一要做的事情。但如果Tail
变成[a|Tail2]
,则需要测试Tail2
是否为列表的新的时条件。
解决方案
1.获取当条件
我已经实现了一个谓词,它将部分列表与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.条件反射时递归
check_on_fixed_length(List, Goal):-
(
condition_fixed_length(List, Condition)
->
when(Condition, check_on_fixed_length(List, Goal))
;
call(Goal)
).
查询示例
假设我们想在L
的大小固定的情况下检查L
的所有元素都是a
:
?- 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.