在Prolog中进行协同处理:当参数是一个列表时(它具有固定的长度)

时间:2015-01-19 12:03:18

标签: prolog logical-purity prolog-coroutining

问题

一旦列表的长度已知/固定,是否可以安排目标执行,或者如评论中指出的@false,给定的参数变为[适当的]列表?这条线上的东西:

when(fixed_length(L), ... some goal ...).

只能使用?=/2nonvar/1ground/1,/2;/2来构建条件,而且似乎它们不是很有用看整个清单。

作为进一步的细节,我正在寻找能够提供的解决方案。

动机

我认为当想要使用谓词p(L)来检查列表L的属性但不以生成方式使用它时,这种情况可能会有用。

E.g。可能是[出于效率或终止原因]如果p1(L), p2(L)具有固定长度(即L是列表),则优先按此顺序执行以下联合L,反之亦然p2(L), p1(L)否则(如果L是部分列表)。

这可能是这样实现的:

when(fixed_length(L), p1(L)), p2(L).

更新

我确实实现了solution,但它缺乏纯度。

2 个答案:

答案 0 :(得分:2)

如果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,为type_error(list,[a|nonlist])生成sort([],[a|nonlist]),否则将替换为:

   when(nonvar(Bool),
      ( Bool == true -> Goal_0 ; throw(error(type_error(list,L), _)).

许多系统包含一些特定于实现的内置函数,如'$skip_list',可以快速遍历列表,您可能希望在此处使用它。

答案 1 :(得分:1)

我设法回答了我自己的问题,但没有用纯粹的解决方案。

一些观察

在编写一个程序时遇到的困难是在精确地知道列表的长度时调度某些执行目标,这是实际情况可能会改变的事实。考虑一下:

when(fixed_length(L), Goal)

如果L未绑定或最后一个尾未绑定,则列表的长度可能会更改。假设我们有这个论点L = [_,_|Tail]。仅当L具有固定宽度时,Tail才具有固定宽度(换句话说,如果L是列表,则T是列表)。因此,检查Tail的条件可能是最初要做的唯一事情。但是,如果Tail成为[a|Tail2]新的时间条件,则需要测试Tail2是否需要列表。

解决方案

<强> 1。获得时间条件

我已经实现了一个谓词,该谓词将部分列表与when-condition相关联,该when-condition表示它何时可能成为列表(即nonvar(T) T最深的尾部< / em>的)。

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的大小修复后检查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.