2

问题

一旦列表的长度已知/固定,是否可以安排目标执行,或者正如@false 在评论中指出的那样,给定的参数变成 [proper] 列表?沿着这条线的东西:

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

何时条件可以使用?=/2, nonvar/1, ground/1, ,/2, and ;/2only 来构造,并且在查看整个列表时它们似乎不是很有用。

作为进一步的细节,如果可能的话,我正在寻找一种呈现的解决方案。

动机

我认为当人们想要使用谓词p(L)来检查 list 的属性L但不以生成方式使用它时,此条件可能很有用。

例如,[出于效率或终止原因]如果具有固定长度(即是一个列表),则可能会更喜欢p1(L), p2(L)按此顺序执行以下连词,否则以相反的顺序执行(如果是部分列表)。LLp2(L), p1(L)L

这可能是这样实现的:

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

更新

我确实实施了一个解决方案,但它缺乏纯度。

4

2 回答 2

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])for sort([],[a|nonlist]),否则将其替换为:

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

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

于 2015-01-19T17:44:46.110 回答
1

我已经设法回答了我自己的问题,但不是纯粹的解决方案。

一些观察

当一个列表的长度已知时,编写一个计划执行某个目标的程序遇到的困难是实际条件可能会改变。考虑一下:

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.
于 2015-01-19T13:11:27.660 回答