Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在Prolog中改进一系列列表的生成_List_Prolog_Range_Generator - Fatal编程技术网

List 在Prolog中改进一系列列表的生成

List 在Prolog中改进一系列列表的生成,list,prolog,range,generator,List,Prolog,Range,Generator,我对Prolog相当陌生,并且越来越喜欢它。我想知道这个实现是否可以进一步推广或改进,它是否是惯用的Prolog代码 %% range/2 range(End, List) :- End > 0, !, range_ascend(0, End, 1, List). range(End, List) :- End < 0, range_descend(0, End, 1, List). %% range/3 range(Start, End, Lis

我对Prolog相当陌生,并且越来越喜欢它。我想知道这个实现是否可以进一步推广或改进,它是否是惯用的Prolog代码

%% range/2
range(End, List) :-
    End > 0, !,
    range_ascend(0, End, 1, List).

range(End, List) :-
    End < 0,
    range_descend(0, End, 1, List).

%% range/3
range(Start, End, List) :-
    ((Start =< End) ->
        (range_ascend(Start, End, 1, List))
    ;
        (range_descend(Start, End, 1, List))).

%% range/4 (+Start, +End, +Step, -List)
range(Start, End, Step, List) :-
    ((Start =< End) ->
        (range_ascend(Start, End, Step, List))
    ;
        (range_descend(Start, End, Step, List))).

range_descend(Start, End, _, []) :-
    End >= Start, !.
range_descend(Start, End, Step, [Start|Rest]) :-
    Next is Start - Step,
    range_descend(Next, End, Step, Rest).

range_ascend(Start, End, _, []) :-
    Start >= End, !.
range_ascend(Start, End, Step, [Start|Rest]) :-
    Next is Start + Step,
    range_ascend(Next, End, Step, Rest).
%%范围/2
范围(结束,列表):-
结束>0!,
范围上升(0,结束,1,列表)。
范围(结束,列表):-
结束<0,
下降范围(0,结束,1,列表)。
%%射程/3
范围(开始、结束、列表):-
((开始=<结束)->
(范围上升(开始、结束、1、列表))
;
(下降范围(开始、结束、1、列表)))。
%%范围/4(+开始,+结束,+步骤,-列表)
范围(开始、结束、步骤、列表):-
((开始=<结束)->
(范围上升(开始、结束、步骤、列表))
;
(下降范围(开始、结束、步骤、列表)))。
下降范围(开始、结束、[]):-
结束>=开始!。
下降范围(开始、结束、步进、[开始|休息]):-
下一步是开始步骤,,
下降范围(下一步、结束、步骤、休息)。
上升范围(开始、结束、[]):-
开始>=结束!。
上升范围(开始、结束、步进、[开始|休息]):-
接下来是开始+步骤,
上升范围(下一步、结束、步骤、休息)。

实现的主要问题之一是它只能“单向”工作,即当
End
设置为某个值时,代码工作正常,但当它是一个变量时,代码不工作:

?- range(X,[0,1,2,3]).
ERROR: >/2: Arguments are not sufficiently instantiated
也许您不需要这样的行为来工作,但在Prolog中,谓词作为一个真正的关系,以多种不同的方式工作,这通常是可取的,也是优雅的

然而,实现这样的谓词通常比以函数方式实现它们要困难得多,特别是如果您是Prolog的初学者

我不打算详细讨论如何具体改进代码(我认为这更像是代码审查SE站点的一个问题)。然而,我在下面介绍了一个行为比您更好的范围谓词:

range(I, S, [I|R]) :-
    I #=< S,
    if_(I = S,
        R = [],
        (   J #= I + 1,
            range(J, S, R)
        )
    ).
我认为您可以看到这里显示了多少行为,以及仅使用一个谓词访问所有行为是多么有用


该谓词使用约束逻辑编程(clpfd库)。CLP允许写入整数之间的关系(即
#=我觉得有点奇怪,在
range/2
的情况下,如果
End
为负数,则您决定生成降序列表。此外,它似乎没有考虑
End=0
Xs=[0,1],range(1,Xs).
错误地成功,而
范围(1,Xs),Xs=[0,1]。
错误地失败。因此谓词不稳定。向执政官致意!OP的主要问题是缺乏稳定性。
库(reif)
可用于和!
?- range(0,5,L).             % Same behavior as your predicate
L = [0, 1, 2, 3, 4, 5].

?- range(-5,0,L).            % Different behavior from your predicate, but logically sounder
L = [-5, -4, -3, -2, -1, 0]

?- range(1,S,[1,2,3,4,5]).   % Finding the max of the range
S = 5 ;
false.

?- range(I,S,[1,2,3,4,5]).   % Finding both the min and max of the range
I = 1,
S = 5 ;
false.

?- range(I,S,[1,2,X,Y,5]).   % With variables in the range
I = 1,
S = 5,
X = 3,
Y = 4 ;
false.

?- range(1,S,L).             % Generating ranges
S = 1,
L = [1] ;
S = 2,
L = [1, 2] ;
S = 3,
L = [1, 2, 3] ;
S = 4,
L = [1, 2, 3, 4] ;
…

?- range(I,1,L).             % Generating ranges
I = 1,
L = [1] ;
I = 0,
L = [0, 1] ;
I = -1,
L = [-1, 0, 1] ;
I = -2,
L = [-2, -1, 0, 1] ;
…

?- range(I,S,L).             % Generating all possible ranges
I = S,
L = [S],
S in inf..sup ;
L = [I, S],
I+1#=S,
S#>=I,
dif(I, S) ;
L = [I, _G6396, S],
I+1#=_G6396,
S#>=I,
dif(I, S),
_G6396+1#=S,
S#>=_G6396,
dif(_G6396, S) ;
…