julia:在嵌套的 for 中使用索引标识符两次

julia: Using an index identifier twice in a nested for

我在嵌套的 for 循环中意外地使用了同一个计数器两次:

for i in 1:2
    println(i)
    for j in 1:2
        for i in 5:6
            i += 1
            println(i, " ", j)
        end
    end
end

编译没有问题并生成

1
6 1
7 1
6 2
7 2
2
6 1
7 1
6 2
7 2

当我意识到发生了什么事时,我大吃一惊。这种行为是故意的吗?由于这会导致意外行为,是否有任何方法可以让编译器将其标记为错误?

举个例子,Fortran在编译类似代码时抛出错误:

program testfor

integer :: i, j, k

do i = 1,2
    do j = 1,2
        do i = 5,6
            i = i+1
            write(*,*) i, j
        end do
    end do
end do

end program testfor

另存为ftest.f90,然后用$:gfortran ftest.f90 -o ftest编译显示两个错误:

ftest.f90:7:18:

    5 | do i = 1,2
      |          2        
    6 |     do j = 1,2
    7 |         do i = 5,6
      |                  1
Error: Variable 'i' at (1) cannot be redefined inside loop beginning at (2)
ftest.f90:8:19:

    7 |         do i = 5,6
      |                  2 
    8 |             i = i+1
      |                   1
Error: Variable 'i' at (1) cannot be redefined inside loop beginning at (2)

简短回答:是的,它是完全有意的,绝对合理且一致。

长答案:您的代码中有两件事导致观察到的行为,值得指出。

  1. 名称隐藏(如上述评论中所述)。实际上这里有三个独立的变量,其中两个恰好被称为 i。虽然内部 i 在范围内,但无法访问外部 i.

  2. 范围循环。从您编写代码的方式来看,我假设您希望这种 for 循环到 运行 就像在 C 中一样,例如:让我们有一个循环变量,它在每个循环中递增。至少最内层循环中的显式额外增量表明了这一点。然而,在 Julia 中,for 循环 遍历可迭代对象 ,在本例中为 Range 对象。最重要的部分:迭代的当前状态存储在隐藏变量中。您迭代的变量的值对状态绝对没有影响。因此,显式递增 i 不会影响内循环的状态,隐藏 i 也不会影响外循环的状态。两个循环都在预定的范围内继续运转。