B-Prolog 中带累加器的嵌套循环 [英] Nested loops with accumulators in B-Prolog

查看:61
本文介绍了B-Prolog 中带累加器的嵌套循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

B-Prolog 具有逻辑循环.例如,这就是我们如何计算 [1,2,3] 的总和:

B-Prolog has logical loops. For example, that's how we can calculate sum of [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)

另一种变体,在外循环的局部变量列表中不包括 Sb:

Another variant, not including Sb in the list of local variables of the outer loop:

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 中使用带累加器的嵌套循环?

Is it even possible to have nested loops with accumulators in B-Prolog?

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

My B-Prolog version is 8.0#1.

推荐答案

你的程序在编译时正确运行.

Your program runs correctly when compiled.

|?- cl(谢尔盖)

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

解释器肯定有问题.这个累加器的东西非常丑陋,我从不使用它.在 B-Prolog 的后继者 Picat 中,您可以使用 := 来更新"变量.

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.

    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.

这篇关于B-Prolog 中带累加器的嵌套循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆