Good programming practices: Should I use the `dimension` attribute?

Hello, Fortran Community! I am currently writing a subroutine in Fortran that works with arrays. Among other dummy variables, there is an input array y0 and an output one y1. Part of the header of my subroutine looks like this:

integer, parameter :: rp = kind(1.0d0)
real(kind = rp), intent(in) :: x0, y0(:), h, smin, smax
real(kind = rp), intent(out) :: y1(size(y0))

I am wondering, in the spirit of good programming practices/preferred programming styles, is it preferred to declare the arrays y0 and y1 with the dimension attribute? Like this:

integer, parameter :: rp = kind(1.0d0)
real(kind = rp), intent(in) :: x0, h, smin, smax
real(kind = rp), dimension(:), intent(in) :: y0
real(kind = rp), dimension(size(y0)), intent(out) :: y1

The first one seems shorter and more elegant to me, but the latter seems more clear.

On a second related matter, considering that y1 has the same shape as y0, would it be considered correct to declare it as follows?

real(kind = rp), intent(out) :: y1(:)

Or should I use the y1(size(y0)) version?

Thank you very much in advance for your answers!

1 Like

Kargl’s response is a good explanation of the Occam’s razor that one should follow not just in coding, but in everyday logic. To extend his response, you may want to use it if it leads to more concise code, for example, when you have many declarations with the same shape in the same place.

Occam’s razor states the simpler solution is preferable - not the shortest. What “simpler” means is everyone’s interpretation of the term I guess, but to me the dimension attribute makes the code more clear, therefore I use it religiously. Yes, it may require a few additional lines of code, since arrays of different dimensions must be declared separately, but that’s exactly the point: clearly distinguish them.
Granted, it is a minor issue (if you can call it an “issue” at all), but wrong solutions to minor issues tend to accumulate, eventually making the code harder to read and understand. And good luck understanding your own code, if it was written half a year ago, and it wasn’t written in a clear manner.

Last but definitely not least, following the F standard is always a good idea in my opinion. Although not very common nowadays, F is a subset of modern Fortran that eliminates old or deprecated features of the language, as well as everything that might confuse the compiler or make the code harder to understand. It also makes data hiding imperative. The F standard enforces many rules. To name a few: arrays must be declared with the dimension attribute, functions must always have the result attribute (even if they are not recursive), you cannot use external functions but should use interface instead, modules must always be declared as private with public procedures clearly declared as such, etc. Everything not following the rules is treated as a syntax error without mercy. Personally, I like that style. Not only it makes the code easier to read, it also eliminates mixing old-style Fortan with modern Fortran - a very common and annoying programming style (especially by new programmers).

2 Likes

I recommend against the use of y1(size(y0)) as it doesn’t do what you think. An explicit shape dummy argument triggers element association, meaning that the actual argument gets associated element-wise with the dummy array regardless of if the actual is the same shape or even rank. This leaves open possibilities of all kinds of bugs. I’d recommend

real(kind=rp), intent(out) :: y1(:)

if (size(y1) /= size(y0)) error stop "arguments of different size"
3 Likes

Generally I agree but would advocate against religious use. There are, and quite often, situations when one declares arrays obviously related but of different shape. Say, linear equations system, with the main and augmented arrays, the RHS and solution vectors, all defined by single value N:

REAL :: A(N,N), AA(N,N+1), B(N), X(N)

looks simpler and clearer to me than three separate declarations with DIMENSION attribute.

1 Like

As you can gather from the responses so far, it’s totally up to you. FWIW, we cover this item in the stdlib style guide, which recommends not using dimension in general and using it in exceptional cases.

1 Like