模仿一个简单的循环:
start = something;
incr = something_else;
end = yet_something_else; /* all three are numerical values, int or float */
while (start <= end) {
/* do something for its side effect, for example: */
printf("%d %d\n", start, start*start);
start += incr;
}
我可以写:
loop1(Start, End, _Incr) :-
Start > End, !. % yes, the cut is necessary!
loop1(Start, End, Incr) :-
Start =< End,
/* do something for its side effect, for example */
format('~d ~d~n', [Start, Start*Start]),
Next is Start + Incr,
loop1(Next, End, Incr).
或:
loop2(Start, End, Incr) :-
( Start =< End
-> format('~d ~d~n, [Start, Start*Start]),
Next is Start + Incr,
loop2(Next, End, Incr)
; true
).
loop/3
必须(并且将始终)调用所有参数实例化为数字。
我应该使用第二个版本,对吗?唯一的理由是,在介绍性的Prolog材料中几乎没有if-then-else结构,我无法弄清楚为什么(Learn Prolog Now!,例如,否则是一个很好的介绍性材料,没有甚至提到它!)。与此同时,每个方向都会随意飞行。
感谢您的帮助!
答案 0 :(得分:1)
我不知道他们为什么不提它。所有实用程序员都使用它。
但如果用故障驱动的循环重写代码,我们可以避免使用cut / if-then-else。
loop(From, To, Incr, Val) :-
From =< To,
( Val = From
; Next is From + Incr,
loop(Next, To, Incr, Val)
).
print_squares(Start, End, Incr) :-
loop(Start, End, Incr, Val),
Square is Val * Val,
format('~d ~d~n', [Val, Square]),
fail
;
true.
在Incr = 1的情况下,您可以使用标准库中的/ 3:
print_squares(Start, End) :-
between(Start, End, Val),
Square is Val * Val,
format('~d ~d~n', [Val, Square]),
fail
;
true.
如果你懂俄语或者可以翻译它,我可以推荐我的书http://sourceforge.net/projects/uranium-test/files/prolog/speed_prolog.pdf/download作为Prolog的介绍性文章。
答案 1 :(得分:1)
我的首选方式,类似于结构化编程,介于/ 3和forall / 2之间。
?- forall(between(1,3,N), writeln(N)).
这是来自ICLP2013竞赛的“应用”示例:
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' )).
产量
2 ?- [icecream].
% icecream compiled 0.00 sec, 10 clauses
true.
3 ?- icecream(5).
()
(())
(( ))
(( ))
(( ))
/\/\/\/\/\/\
\ /
\ /
\ /
\ /
\ /
\/
true.
答案 2 :(得分:0)
可能是枚举(浮点)数字序列的更好方法:
sequence(First, Step, Last, R) :-
D is Last - First,
sign(Step) =:= sign(D),
N is floor(D / Step),
between(0, N, X),
R is First + X * Step.
此解决方案的一个优点是它不会累积像Next is This + Step
这样的浮点错误。