B-Prolog中带累加器的嵌套循环

B-Prolog中带累加器的嵌套循环,prolog,b-prolog,Prolog,B Prolog,B-Prolog具有逻辑循环。例如,我们可以这样计算[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 但当我尝试使用累加器的两个嵌套循环时,会出现错误: test2 :- foreach(_A in 1..3, [Sb], ac(Sa, 0

B-Prolog具有逻辑循环。例如,我们可以这样计算[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
但当我尝试使用累加器的两个嵌套循环时,会出现错误:

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)
另一个变量,不包括外部循环局部变量列表中的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)
甚至可以在B-Prolog中使用带累加器的嵌套循环吗

我的B-Prolog版本是8.0#1。

似乎显示了一个嵌套循环,扁平化:

?-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)]
我们只需要恢复内循环结束条件。看看这是否有效:

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)). 
如果
A
s中可能有重复,只需按文档所示索引即可:

?-foreach((A,I) in ([a,b],1..2), ac(L,[]), L^1=[(A,I)|L^0]).
L = [(b,2),(a,1)]
并中断
I
中的更改


(未测试)。

您的程序在编译时运行正常

|?-cl(谢尔盖)

翻译一定有问题。这个东西很难看,我从来没用过。在B-Prolog的后继者Picat中,可以使用:=来“更新”变量

    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)). 
更好的方法是使用列表理解

    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)). 

编译器将总和编译成使用“:=”的程序。由于列表不是实际构造的,因此没有开销。

在实际代码中,内部循环的目标是否取决于外部循环的变量或累加器?在这里显示的代码中,
Sb
是常量,可以预先计算。我想你的真实代码不是这样的?是的,我只是提供了非常简单的无意义代码来说明带有累加器的嵌套循环的问题。是的,我也这么怀疑。:)请注意,
(^)/2
的用法与
Sb^1是Sb^0+B
一样,与ISO可计算函子
(^)/2
冲突。看见
    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)).