The Stack Overflow thread What is the point of BLOCK in Fortran? presents some interesting applications of BLOCK.
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.
I think it might be the other way around. Compilers can inline internal subprograms and they have been around longer than BLOCK.
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.
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.
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.
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ā¦
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
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
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.
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 )
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.