`block` syntax and my confusion

The Stack Overflow thread What is the point of BLOCK in Fortran? presents some interesting applications of BLOCK.

3 Likes

It would be concise and natural for programmers coming from other languages to write the block in the program above as

  block
     real    :: xsum=0.0,xran
     integer :: j=0
     do
        j = j + 1
        call random_number(xran)
        xsum = xsum + xran
        if (xsum > 1.0) exit
     end do
     nsum(i) = j
  end block

but that triggers the implicit SAVE behavior of Fortran (similar to variable declarations in procedures) and gives nonsense. There have been calls to remove implcit SAVE from Fortran.

1 Like

I think it might be the other way around. Compilers can inline internal subprograms and they have been around longer than BLOCK.

1 Like

A block in a tight loop would suffer if you declared local allocatable variables and use them. There is overhead in allocating and deallocating them. Also, you give up code motion for optimization across the block boundary.

1 Like

Actually, I also think of BLOCK as a sort of missed opportunity.

Doing

block
  integer i 
  do i = 1, n
  end do
end block

instead of something like

do integer :: i = 1, n
end do

is not only quite verbose but also less readable.

5 Likes

Yes!! One of the features I want most of all in Fortran is simply to be able to do do integer :: i = 1, n or do integer(ik) :: i = 1, n. It should compile down to the equivalent of your block example. Having loop counters polluting the variables declarations section really irks me.

In Fortran the loop variable has a defined value after the loop, usually 1 + upper_bound. For the syntax above, is i available after the loop? When does it stop being available? With BLOCK and END BLOCK the programmer can delineate the scope of the loop variable.

1 Like

This would irritate me more

integer :: n, m, p

do integer :: i = 1, n
  do integer :: j = 1, m
     do integer :: k = 1, p
        ! ...
     end do
  end do
end do

than this

integer :: i, j, k, n, m, p

do i = 1, n
  do j = 1, m
     do k = 1, p
        ! ...
     end do
  end do
end do

If I remember Steveā€™s talk from FortranCon correctly, Fortran 202x does plan to introduce integer declaration in implicit do loops:

integer :: a(5)

a = [(i, integer :: i = 1, 5)]

I find this quite attractive.

Ultimately, I prefer to just accept that C and Fortran are different languages which require different coding practices. If not we can start asking ourselves the reason why canā€™t integer be abbreviated as int, why does subroutine need to be longer than void, why do we even need the function statement when the type would do, and so forthā€¦

4 Likes

In my vision, I would be unavailable after the loop. If the programmer wants to continue to use I outside the loop, then itā€™s justified to declare it in the declaration section outside the loop. That said: if the value of I is meaningful outside the loop, it shouldnā€™t be called I, it should be saved under something more meaningful.

integer :: target_index = 0

FIND_LP: do integer :: i = 1, n
    if (somedata(i) == target_value) then
        target_index = i
        exit FIND_LP
    end if
end do FIND_LP
1 Like

For that syntax the variable does not exist outside of the loop at all. Therefore the value is not available either. Not unlike for (int i=1,i<n,i++){}.

The unavailability of the loop counter after the loop is the price that I consider to be quite minor.

I see no reason to use the alternative syntax for such triple loops.

Your cleaner solution is fewer characters but actually illustrates a problem. Variables n, m, and p are critical, meaningful values in your program, while i, j, and k are just throwaway loop counters, yet theyā€™re all declared on the same line and look the same.

An more realistic program using this paradigm, while more verbose in character count, is ultimately cleaner (IMO):

integer :: num_widgets      ! number of widgets received from subroutine x
integer :: num_dims1        ! blah
integer :: num_etc          ! etc

do integer :: i = 1, num_widgets
  do integer :: j = 1, num_dims1
     do integer :: k = 1, num_etc
        ! ...
     end do
  end do
end do
1 Like

This form of inferring variable types in Golang is very powerful:

i := 1.0        // float type
g, h := 123, "hello"         // int and string type

The types of g and h (int and string) will be inferred automatically by the compiler.

This is the preferred form of using variables, but it can only be used in the body of a function, not in the declaration and assignment of global variables. Use the operator := to efficiently create a new variable, which is called an initialization declaration.

Take a look at its familiar :, it looks like the :: in integer :: i of Fortran. :crazy_face:

1 Like

Working out the semantic aspects in terms of language standard requirements and specifications that are consistent with DO construct in the current standard is the main challenge here. There was a proposal along the same lines by @vsnyder but it didnā€™t gain traction:
https://j3-fortran.org/doc/year/18/18-242.txt

But from a syntax aspect, chances are very high parentheses will be involved to get to the semantics of a construct entity if at all something like this makes it into the language:

do ( integer :: i = 1, n )
1 Like

Yeesh, I hope parentheses arenā€™t required, but Iā€™d take it over nothing!

BLOCK is not treated as a subprogram. It is just a nested scope, exactly analogous to {} in C. The compiler needs to have a scoped symbol table, but Fortran 90 requires that anyway. BLOCK is no big deal to compilers.

3 Likes