What are your favorite and least favorite things about Fortran?

In the interests of balance I like % and don’t see any point in trying to change it for something else. Using ‘.’ instead (on compilers that support it) causes strange compiler problems when making method calls inside compound ‘if’ statements.

Favourite:

  • native array support
  • structure (modules / submodules)
  • oo

Least favourite:

  • the amount of code that has to be written to get round the lack of templates
  • the general verbosity - I’d much prefer to declare a dummy variable where it’s used (like C++) than having to give it a line at the top of the procedure
  • not really the fault of the language but the lack of a decent IDE on all platforms can be a real problem, perhaps a tutorial on the options somewhere?
2 Likes

We should add this functionality to stdlib to be able to save in binary and load in numpy (and Matlab):

Go ahead and upvote the issue.

2 Likes

Save and load in binary, compatible with NumPy/Matlab and others ·

Nice!

others: some common image and sound files.
xtc file (portable format for trajectories), maybe. :grin:

1 Like

Reading and writing common image formats, ppm, tiff, jpeg, png · Issue #45 · fortran-lang/stdlib · GitHub

Add some common sound files (wav, flac, ...) · Issue #487 · fortran-lang/stdlib · GitHub

This is a good idea, but should probably first start as a separate package.

Upvoted!

1 Like

(Sorry for revitalizing this old post)

Favorite:

  1. Native support for matrices (I mean automatic arrays in particular; allocatable arrays are OK but automatic arrays are closer to mathematics).

  2. Intrinsic support for matrix/vector operations: matrix addition/multiplication, transpose, slicing, broadcasting, …; without such intrinsic functionalities, a language should not be called a “formula translator”.

  3. High performance.

Least favorite (sorry, I have more than three):

  1. The robustness and performance of automatic arrays and intrinsic matrix/vector operations can still be improved (largely).
    Speaking about robustness, automatic arrays and intrinsic matrix/vector operations can lead to stack overflows (segfaults) under the default settings of some major compilers; this kind of major failure seems to be weirdly permitted by the Fortran community (e.g., see this 13-year old report to Intel and the latest experiment reproducing the same failure); this is unimaginable in other popular languages with the same functionalities, e.g., MATLAB/Python/R/Julia, unless you are encountering a bug that has to be fixed.
    As for performance, the intrinsic matrix/vector operations in Fortran normally cannot achieve the same performance as the intrinsic matrix/vector operations in MATLAB under default settings unless you are capable enough to make your compiler link to the correct library, which may be nontrivial as discussed in another post on this discourse. I know, MATLAB achieves high performance only because of the Fortran code underneath, but it is difficult to understand why Fortran itself does not optimize its intrinsic matrix/vector operations (under the default settings, without the need for particular options) in the same way.
    As mentioned in many posts above, the native support for matrices (arrays) and matrix/vector operations is one of the core strengths of Fortran. I do not see any reason why the community should be indifferent to its robustness and performance in this regard.

  2. Lack of support for functions with multiple returns. True, we have subroutines that can return arbitrarily many results, but functions are less error-prone and often more intuitive.

  3. Lack of interactivity. Fortunately, LFortran @certik is solving this problem.

  4. Lack of support for logical indexing of arrays, which exists in all other popular modern languages used in scientific computing, namely MATLAB/Python/R/Julia.

  5. Implicit mapping.

2 Likes

But, functions that only return a single result are closer to mathematics :wink:

1 Like

Tuples are a thing in math. Multiple returns are just returning a tuple.

2 Likes

With the ability to return a scalar derived type or an array of derived types, possibly allocatable, Fortran functions are already pretty flexible, although returning multiple values would be nice.

1 Like

Favourite thing that I don’t think was already mentioned: complex arithmetic as part of the language rather than a library having to be fetched, with many complex intrinsic functions (though I had to roll my own for some that have real but not complex intrinsics)

Least favourite: nncarlson complained of no reliable free compiler. My experience of reporting over 100 compiler bugs is that free and commercial compilers have both had bugs, but gfortran fixed them faster. Once I complained about a commercial compiler’s bug and was told the standard was ambiguous; the next version of the standard removed the ambiguity.

1 Like

My least favorite feature about Fortran is that the linker has not been defined in the standard, especially a minimum functionality.
I think that INTERFACE should be automatic and reviewed at the link stage, especially for the count of subroutine and function arguments. The report should not be errors, but warnings that can be over-ruled, as in the case of F77 wrappers with mixed variable types.

This is actually available in the NAG Fortran compiler. It will produce an error if any argument mismatch is found, the check is actually global to all files linked. GFortran has a similar feature since version 10, limited to a single file.

Favourites (I am a domain expert not a computer scientist)

  • verbosity = a language that tells me what it is doing without having to remember too much
  • array handling
  • language defined features that others have to pull in libraries to do

Least favourite

  • lack of simple introspection: I would really use NAME(), ACTUAL_NAME(), PLACE() functions such as
x = 9.0
call foo( x, 7.4)
...
subroutine foo(a,b)
real, intent(in) a,b

print *, place() ! prints prog name: module name: procedure_name: block_name
print *, name(a)//' = ', a ! prints a = 9.0
print *, actual_name(a) // ' = ' , a ! prints x = 9.0
print *, actual_name(b) ! returns, say, #7.4

! with component equivalents

print *, a % name // ' = ', a
print *, a % actual_name // ' = ', a

Using actual_name() with a non-dummy argument could return the same as name

I think there is utility in a SCOPE() function too, but I may already have said more than enough for compiler writers to put a price on my head. I just feel features like this would be so useful in error handling.
Please don’t get ratty with me if these features already exist.

4 Likes

I often define

character (len=*), parameter :: msg = "in module_name::foo, "

and use msg in error messages. One could write a script that defines such a named constant within every procedure. I would like a place() function, but a difficulty of having place() in the language is that the compiler may inline a procedure, so that it does not exist in the executable. Maybe allow the compiler to print UNKNOWN if the information has been lost? Do C, C++, and Java have introspection?

A relevant thread is debugging - Fortran query and print out function or subroutine name - Stack Overflow.

I like the idea, if not exactly the specifics.

We have compiler_version and compiler_options, so there is some precedent for some kind of introspection.

place() is an interesting idea, and leaves plenty of room for “processor dependent” output, so I think it could be workable. file() and line() have been suggested in the past, but since the standard has no notion of source files. I could imagine the description in the standard being something like “returns a character value of default kind that is a processor dependent representation of the location within the current translation unit”.

name() seems a bit superfluous. You had to type the name of the variable there anyway, just put it in quotes. It would even be 4 characters shorter.

actual_name seems like it probably has too many cases where it doesn’t work. For example, what if the actual argument was a literal? (i.e. 3.14), or even worse, what if the argument was an expression? (i.e. 9.0 / 3.0) In those cases there is no actual name.

2 Likes

Several languages seem to provide such functionality, for example, in D:

module mytest;
import std.stdio;

void myfoo( int num )
{
    writeln( __MODULE__ );
    writeln( __FUNCTION__ );
    writeln( __PRETTY_FUNCTION__ );
}

void main()
{
    myfoo( 100 );
}

$ ldc2 mytest.d && ./a.out
mytest
mytest.myfoo
void mytest.myfoo(int num)

and in Swift:

If the Fortran preprocessor is planned to be standardized, it may be very useful to include such macros.

I am very glad to note that the LFortran webpage lists the native support for matrices and matrix/vector operations as the top two highlights of Fortran:

This is reassuring, because I thought I was among the minority when regarding such support as a core strength of Fortran, and I even thought I totally misunderstood modern Fortran.

Now, it seems that my understanding of Fortran is at least akin to the viewpoint of LFortran developers. Great! This viewpoint is also an indication that LFortran will pay more attention to the robustness and performance of intrinsic array procedures such as matmul. This gives me yet another reason to look forward to using LFortran for my projects, in addition to many others including interactivity.

1 Like

Some kind of deep introspection feature would be huge! What I want is the ability to write parser libraries that you can send arbitrary variables to, and it can serialize/deserialize them without requiring the user to manually type all the variable names, etc. The one place in Fortran that has anything like that is the namelist feature. But, if we had introspection, we could create a similar feature for modern formats like JSON or TOML very easily. We’d need variable name, rank, kind, size, etc, and also the ability to traverse derived types.

I am new to Fortran and I also found the use of the (%) a bit perplexing. And I agree that the dot (.) would be so much nicer …

2 Likes

You can define a .plus. operator and write

c = a.plus.b

If . were allowed to designate a structure component this code would be ambiguous.