在prolog上实现"For loop"

YUR*_*KIY 2 algorithm prolog

如何使用计数器的递归和截止周期(如for i: = 1 downto N do <operator>)?

Nic*_*rey 6

简短的回答是你没有.

Prolog是一种语言,而不是程序语言.它来自谓词演算.您可以根据事实和规则("数据库")来描述问题空间.这形成了连接的有向图的集合.

您制定了一个初始目标,描述了您的"问题"的解决方案,并让推理引擎找到解决方案(如果有的话).

推理引擎以您给出的初始目标开始.它根据数据库对其进行评估,随着图表的移动,回溯失败,直到找到解决方案(或不找到解决方案).回溯到初始目标将导致它寻找下一个解决方案,如果有的话.

因此,诸如循环之类的程序性构造的概念是非惯用的(至少可以说)和(至少在我的经验中)几乎是性能不佳的保证.


Cap*_*liC 6

我天真的实现,被视为/ 3之间的扩展

:- module(loop, [upto/4, downto/4]).

upto(Low,High,_Step,Low) :- Low =< High.
upto(Low,High,Step,Var) :-
    Inc is Low+Step,
    Inc =< High,
    upto(Inc, High, Step, Var).

downto(Low,High,_Step,High) :- Low =< High.
downto(Low,High,Step,Var) :-
    Dec is High-Step,
    Dec >= Low,
    downto(Low, Dec, Step, Var).
Run Code Online (Sandbox Code Playgroud)

用法:

8 ?- forall(upto(0,6,3,V),writeln(V)).
0
3
6
true.

9 ?- forall(downto(0,6,3,V),writeln(V)).
6
3
0
true.
Run Code Online (Sandbox Code Playgroud)

另一个例子,最简单的问题@今年Prolog编程比赛:

icecream(N) :-
    loop(N, top(N)),
    left, loop(N+1, center), nl,
    loop(N+1, bottom(N)).

:- meta_predicate loop(+, 1).

loop(XH, PR) :-
    H is XH,
    forall(between(1, H, I), call(PR, I)).

top(N, I) :-
    left, spc(N-I+1), pop,
    (   I > 1
    ->  pop,
        spc(2*(I-2)),
        pcl
    ;   true
    ),
    pcl, nl.

bottom(N, I) :-
    left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.

center(_) :- put(/), put(\).

left :- spc(4).
pop :- put(0'().
pcl :- put(0')).
spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).
Run Code Online (Sandbox Code Playgroud)

产量

?- icecream(4).
        ()
       (())
      ((  ))
     ((    ))
    /\/\/\/\/\
    \        /
     \      /
      \    /
       \  /
        \/
true.
Run Code Online (Sandbox Code Playgroud)

注意:第二个片段中的循环与第一个片段无关...