[英]Nested loops with accumulators in B-Prolog
B-Prolog has logical loops. B-Prolog有逻辑循环。 For example, that's how we can calculate sum of [1,2,3]: 例如,这就是我们如何计算[1,2,3]的总和:
test1 :-
foreach(A in 1..3, [], ac(Sa, 0), (
Sa^1 is Sa^0 + A
)),
writeln(sa(Sa)).
?- test1.
test1.
sa(6)
yes
But when I try two nested loops with accumulators, I get errors: 但是当我尝试两个带累加器的嵌套循环时,我得到错误:
test2 :-
foreach(_A in 1..3, [Sb], ac(Sa, 0), (
foreach(B in 1..3, [], ac(Sb, 0), (
Sb^1 is Sb^0 + B
)),
writeln(sb(Sb)),
Sa^1 is Sa^0 + Sb
)),
writeln(sa(Sa)).
?- test2.
test2.
*** error(invalid_argument,(+)/2)
Another variant, not including Sb in the list of local variables of the outer loop: 另一个变体,不包括外部循环的局部变量列表中的Sb:
test3 :-
foreach(_A in 1..3, [], ac(Sa, 0), (
foreach(B in 1..3, [], ac(Sb, 0), (
Sb^1 is Sb^0 + B
)),
writeln(sb(Sb)),
Sa^1 is Sa^0 + Sb
)),
writeln(sa(Sa)).
?- test3.
test3.
sb(6)
*** error(invalid_argument,(+)/2)
Is it even possible to have nested loops with accumulators in B-Prolog? 是否有可能在B-Prolog中使用带累加器的嵌套循环?
My B-Prolog version is 8.0#1. 我的B-Prolog版本是8.0#1。
Your program runs correctly when compiled. 您的程序在编译时正确运行。
| | ?- cl(sergey) ? - cl(sergey)
Compiling::sergey.pl
** Warning: Variable 'Sb' is treated as global in foreach (17-25).
** Warning: Variable 'Sb' is treated as global in list_comprehension (36-38).
compiled in 0 milliseconds
loading...
yes
| ?- test1
sa(6)
yes
| ?- test2
sb(6)
sb(6)
sb(6)
sa(18)
yes
| ?- test3
sb(6)
sb(6)
sb(6)
sa(18)
There must be some problem with the interpreter. 解释器一定有问题。 This accumulator thing is very ugly and I never use it. 这个累加器的东西非常难看,我从不使用它。 In Picat, the successor of B-Prolog, you can use := to "update" variables. 在Picat中,B-Prolog的后继者,您可以使用:=来“更新”变量。
test1 =>
Sa = 0,
foreach(A in 1..3)
Sa := Sa+A
end,
writeln($sa(Sa)).
test2 =>
Sa = 0,
foreach(_A in 1..3)
Sb := 0,
foreach(B in 1..3)
Sb := Sb+B
end,
writeln($sb(Sb)),
Sa := Sa+Sb
end,
writeln($sa(Sa)).
An even better way is to use list comprehension. 更好的方法是使用列表理解。
test1 =>
Sa = sum([A : A in 1..3]),
writeln($sa(Sa)).
test2 =>
Sa = sum([Sb : _A in 1..3, Sb=sum([B : B in 1..3])]),
writeln($sa(Sa)).
The compiler compiles the summations into programs that use ':='. 编译器将汇总编译为使用':='的程序。 As lists are not actually constructed, there is no overhead. 由于列表实际上并未构建,因此没有开销。
http://www.probp.com/manual/node55.html seems to show a nested loop, flattened: http://www.probp.com/manual/node55.html似乎显示了一个嵌套循环,展平:
?-foreach(A in [a,b], I in 1..2, ac(L,[]), L^1=[(A,I)|L^0]).
L = [(b,2),(b,1),(a,2),(a,1)]
We just need to recover the end-of-inner loop condition. 我们只需要恢复内部循环结束条件。 See if this works: 看看这是否有效:
test2 :-
foreach(A in 1..3,
B in 1..3, [], [ac(Sa, 0), ac(La, []) ac(Sb, 0)], (
( ( La^0 = [] ; La^0 = [A] ) % or just (La^0 = [A])
-> % same A, next B
Sa^1 is Sa^0, Sb^1 is Sb^0 + B
; % new A, B-loop has ended
Sa^1 is Sa^0 + Sb^0, writeln(sb(Sb^0)), Sb^1 is 0 + B
),
La^1 = [A]
)),
Sa_final = Sa + Sb, % process the final iteration
writeln(sa(Sa_final)).
If there can be repetitions in A
s, just index them up as the docs show: 如果A
可以重复,只需将其编入索引,如文档所示:
?-foreach((A,I) in ([a,b],1..2), ac(L,[]), L^1=[(A,I)|L^0]).
L = [(b,2),(a,1)]
and break on the changes in I
. 并打破I
的变化。
(Not tested). (未经测试)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.