Should I indent the codes below contains?

Regarding coding style, should I indent the codes below contains?

PS: I guess there should be more details in the indentation subsection of the Fortran Best Practices mini-book.

https://fortran-lang.org/learn/best_practices/style_guide#indentation

Based on my personal experience, f77 syntax, uppercase letters, and lack of indentation are the three major readability killers in Fortran codes. A proper and consistent style of indentation can really make a difference.

I say no. I also recommend against indenting code just because it is in a procedure or in the main program. I do indent code within an if block or do loop, as shown here. Avoiding unnecessary indentation will lead to fewer continuation lines if you limit line length, and code with fewer continuations is easier to read.

In English, you may indent the first line of a paragraph or not indent but have blank lines between paragraphs, as in this message. It would be wasteful and tedious to indent every line in a paragraph except the first.

Here is a Python script to undo some indentation:

# remove the the first nleading spaces from lines of infile 
from sys import argv
infile = argv[1]
nleading = int(argv[2])
fp = open(infile,"r")
for line in fp:
    text = line.rstrip()
    text = text.replace("if(","if (").replace("( ","(").replace(" )",")") # other spacing changes
    text = text.replace("real(dp)","real(kind=dp)")                       # reformat some declarations
    nlen = len(text)
    if nlen > nleading:
        if not text[0:nleading].strip():
            text = text[nleading:]
    print(text)

That said, if you are contributing to a project such as stdlib, you should follow the style of that project.

1 Like

In all the other programming languages I use, codes within a procedure are always indented. I am unsure why you choose not to follow this convention. With all due respect, your example Fortran codes are not easy to read. The stdlib codes do indent the codes within a procedure. For example, see:

I am 100% sure that the codes within a procedure should be indented but unsure if the codes below contains should.

It is a matter of taste, and many people share your view. My style follows that of prolific Fortran 90/95 open source contributor Alan Miller, who did not indent the bodies of modules or procedures but did indent conditionals and loops, and did separate procedures with blank lines, as demonstrated here. I find his codes to be readable.

2 Likes

@fortran4r if possible, let’s allow people to choose the indentation they like and respect that.

For example, I agree 100% with @Beliavsky and follow the same conventions. The stdlib example you posted wastes 8 spaces for any executable code. I do like using 4 spaces and then you very quickly run out of horizontal space. I also like to stick to 80 columns, because then I can have multiple terminals open side by side. The example you posted runs over 80 columns with one comment due to that. It would be easy to fix. Currently it is only using 1 loop. If you increase it to 3 loops which is common, you will run out of space. A typical solution is to give up fitting into 80 columns. But I don’t like doing that, I rather start all executable code at column 1. You can also change from 4 spaces to 3 or 2 spaces.

Now, for LFortran we made this configurable:

$ lfortran fmt tests/subroutine4.f90 
subroutine triad(a, b, scalar, c)
real, intent(in) :: a(:), b(:), scalar
real, intent(out) :: c(:)
integer :: N, i
N = size(a)
do concurrent (i = 1:N)
    c(i) = a(i) + scalar*b(i)
end do
end subroutine triad

$ lfortran fmt --indent-unit tests/subroutine4.f90
subroutine triad(a, b, scalar, c)
    real, intent(in) :: a(:), b(:), scalar
    real, intent(out) :: c(:)
    integer :: N, i
    N = size(a)
    do concurrent (i = 1:N)
        c(i) = a(i) + scalar*b(i)
    end do
end subroutine triad

You can configure the number of spaces to use also.

1 Like

Unlike Physics (with universal laws), computer programming is a set of conventions and opinions from the ground up. So I agree with Beliavsky and Certik this is certainly a personal choice. In practice, however, I have settled with the consensus that anything between

something
end something

should be indented. This includes program, module, submodule, function, subroutine, procedure, type, interface, block, if, and do constructs. The keyword contains feels like else in an if block to me. So I also indent anything after contains. An exception is when the entire block fits within a single display page. This is frequently the case for program; contains; end program. I personally prefer anything that helps readability over less readable alternatives.

7 Likes

I hope most readers will agree this is matter of style with Fortran. Were I to “code in anger,” I would

  1. align CONTAINS with (SUB)MODULE,
  2. indent the body of all the major constructs including ASSOCIATE, BLOCK, IF, etc. and also FUNCTION and SUBROUTINE
  3. use 3 spaces for indentation; two spaces appears too low but four spaces is too wide for me,
  4. Have a space between END, ELSE, etc. and following clause - END IF, ELSE IF, END ASSOCIATE, etc.
  5. Limit uppercase letters to named constants,

To each their own!!

What I am waiting for (or planning to look into options for) is a “View” mode in IDEs where one can define/pick a style and Fortran code can then simply be viewed in that style regardless of how it is in the actual source content.

3 Likes

I agree that indentation of subprogram bodies is largely a matter of personal preference and what you are used to. But there are some tangible advantages to each.

Not indenting saves horizontal space, as @certik mentioned. But if you use 4-space indent and limit to 80 columns you are going to end up continuing lots of lines anyway. And you can eliminate this disadvantage by using smaller indent or longer lines.

Indenting provides better visual separation before subprograms, though you could probably use some kind of banner comment to achieve the same thing.

As @fortran4r mentioned, indenting subprograms is almost universal outside of Fortran. Not indenting is one of the things that makes Fortran look foreign to programmers who use other languages (along with all-caps and fixed form). In my opinion, that is the main reason to indent.

For the non-indenters, do you indent internal subprograms?

2 Likes

I follow the Google C++ Style Guide to use two spaces for indentation for all the programming languages I use. Trading two spaces for readability seems a good deal to me. I agree that using four spaces for indentation is overkill.

Since Fortran will soon remove the line length limit, using indentation should be encouraged even more.

https://google.github.io/styleguide/cppguide.html

I think if you stick to one module per file, it is okay not to indent the module declarations and part after contains. Indentation is there to help the reader tell what a line is nested inside. In this case everything in the file is nested in the module, so that information isn’t needed.

In C++ files that are all inside a one namespace, it is common not to have a level of indentation for the namespace.

3 Likes

Exactly: I view Fortran modules as a C++ namespaces and I do not indent either. It is in fact a common practice in both languages, but not universal.

I do usually indent internal subprograms, that does make it more readable to me.

Indenting insides of functions is a personal choice — I personally actually find it more readable not to indent it. I find 2 spaces not to be enough, and use 4 spaces everywhere (Python, C++, Fortran, …).

But I am happy to contribute to whatever conventions people use in a given file. It’s a bit like an editor choice — just use what you like and what makes sense to you, and let’s respect other people’s different choices.

I am hoping the LFortran’s automatic formatting tool can help format your code the way you like automatically. @fortran4r if you want to help us making it work well for you, please let us know. I would be happy to help fix any bugs that you discover and/or show you how to do it.

I created an issue for this:

Would this be “read only” mode, or would you like to also edit it? Editing it would be quite tough to preserve the original formatting.

2 Likes

Yes, “read only” is all I had in mind!

I haven’t looked into this much yet, since I haven’t had a good Fortran formatter I liked available, but you should be able to accomplish this with just formatter options and git. You can use git checkout and commit hooks to format the code the way you’d like to see it on checkout, and format it in the “project style” on commit. I’d be interested in a demonstration if anybody has tried it.

1 Like