Mar 21, 2015
There is a lot of confusion and misinformation about the Fortran programming language on the internet, and a general ignorance about it among programmers. Most younger programmers who use languages invented five minutes ago probably have never seen it, and may only be dimly aware of it as some obsolete language that nobody uses anymore.
You may be surprised to learn that Fortran is a modern, object-oriented, general-purpose programming language. Fortran is not a programming language created by computer scientists to write operating systems, nor does it include every single programming concept anyone's ever heard of. It is a language designed for computational efficiency and efficient array manipulation, and has a clear uncluttered syntax that can be read and understood by non-experts with only a little effort and training. It is particularly suited for numerical and scientific programming by non-expert programmers such as engineers and scientists. Learning all of Fortran is considerably easier than learning all of C++ (as an example). Sure, you can't do template metaprogramming, but few engineer/scientist types would ever want to do that anyway (besides, it's bad for you and could make you go blind).
By "Fortran", I mean modern Fortran (i.e., Fortran 2003 and 2008, which is the latest standard). Yes, the roots of Fortran go way back to the 1950s. Sure, early Fortran programs were written on punched cards. So what? Latin was once scratched into wax tablets, but that isn't really relevant to modern Italian and French speakers. In fact, the Fortran language has evolved considerably since it was first standardized in 1966. It generally has followed a cycle where a major update is followed by a minor update (1977=minor, 1990=major, 1995=minor, 2003=major, 2008=minor). It has been said that the 2003 update was as big an update to Fortran 95 as C++ was to C! Ten years later, the GNU Fortran compiler is still not fully F2003 compliment (the Intel compiler only recently became so).
People who attempt to enter the world of Fortran programming are easily corrupted and discouraged by misinformation. Even a lot of old-school Fortran users are unaware of the later standards. This is too bad, because modern Fortran is actually quite a respectable programming language for a lot of technical applications. This article is a pretty good overview of Fortran for C/C++ programmers. However, it is outdated, since it is confined to Fortran 95. Most of the limitations it mentions (no procedure pointers, clunky character strings, lack of an intent attribute for pointer dummy arguments, the nonstandardness of the ;
character) have been rectified in subsequent standards.
The fact is the internet is not really the best source of information for modern Fortran. One day, maybe, there will be vibrant community of Fortran users on the internet, extensive online documentation, open source projects, and all your questions will simply be a web search away (cf., Python). But for now, you'll probably have to buy some books. If a book has the numbers 77, 90, or 95 in the title, don't open it, it will only confuse you. This is not to say that there aren't friendly Fortran folk on the internet who will also help you out. Two of the best places to go with questions are the Intel Fortran forum and the comp.lang.fortran newsgroup (yes, apparently, Usenet still exists).
References
- N. Maclaren, Why (and Why Not) to Use Fortran: Instead of C++, Matlab, Python etc., University of Cambridge Computing Service, June 2012.
- L. Phillips, Scientific computing’s future: Can any coding language top a 1950s behemoth?, May 7, 2014 [arstechnica.com]
- Fortran Wiki -- an open venue for discussing all aspects of the Fortran programming language and scientific computing.
- A. Koenig, C Traps and Pitfalls, AT&T Bell Laboratories.
- Why C and C++ are Awful Programming Languages
Feb 16, 2015
I just came across this article from 2005 written by Jef Raskin (probably most famous for having initiated the Macintosh project at Apple) on source code documentation [1]. I agree with much of what he recommends. I have never believed that code can be "self-documenting" without comments, and generally will start writing the comments before I start the actual code. I also like some aspects of Knuth's "literate programming" concept [2].
I do find automatic documentation generators useful, however. There aren't a lot of solutions for modern Fortran projects though. I've not tried to use Doxygen, but am told that support for modern Fortran features is somewhat lacking [3]. ROBODoc is pretty good, although it does not perform any code analysis, and only extracts specific comment blocks that you indicate in the source. A brand new tool called ford is very promising, since it was created with modern Fortran in mind.
I also have an idea that the best code (including comments) should be understandable to a reasonably intelligent person who is not familiar with the programming language. Some languages (Fortran, Python) make this easier than others (C++, Haskell). There is a good article here, discussing the "beauty" of some C++ code (although I disagree with his views on comments). I was struck by the discussion on how to write functions so that more information is provided to the reader of the code [4]. The example given is this:
int idSurface::Split( const idPlane &plane, const float epsilon,
idSurface **front, idSurface **back,
int *frontOnPlaneEdges, int *backOnPlaneEdges ) const;
Of course, if you are not familiar with the C++ *
, **
, and &
characters and the const
declaration, there is no information you can derive from this. It is complete gibberish. Modern Fortran, on the other hand, provides for the declaration of an intent
attribute to function and subroutine arguments. The equivalent Fortran version would look something like this:
integer function split(me,plane,eps,front,back,&
frontOnPlaneEdges,backOnPlaneEdges)
class(idSurface),intent(in) :: me
type(idPlane), intent(in) :: plane
real, intent(in) :: eps
type(idSurface), intent(out) :: front
type(idSurface), intent(out) :: back
integer, intent(out) :: frontOnPlaneEdges
integer, intent(out) :: backOnPlaneEdges
Here, it should be more obvious what is happening (for example, that plane
is an input and front
is an output). The use of words rather than symbols definitely improves readability for the non-expert (although if taken to the extreme, you would end up with COBOL).
References
- J. Raskin, "Comments are More Important than Code", Queue, Volume 3 Issue 2, March 2005, Pages 64-65.
- D. E. Knuth, "Literate Programming", The Computer Journal (1984) 27 (2): 97-111.
- F03/08 supporting Documentation tools, comp.lang.fortran.
- S. McGrath, "The Exceptional Beauty of Doom 3's Source Code", kotaku.com, Jan. 14, 2013.
Feb 16, 2015
I just came across this article from 2005 written by Jef Raskin (probably most famous for having initiated the Macintosh project at Apple) on source code documentation [1]. I agree with much of what he recommends. I have never believed that code can be "self-documenting" without comments, and generally will start writing the comments before I start the actual code. I also like some aspects of Knuth's "literate programming" concept [2].
I do find automatic documentation generators useful, however. There aren't a lot of solutions for modern Fortran projects though. I've not tried to use Doxygen, but am told that support for modern Fortran features is somewhat lacking [3]. ROBODoc is pretty good, although it does not perform any code analysis, and only extracts specific comment blocks that you indicate in the source. A brand new tool called ford is very promising, since it was created with modern Fortran in mind.
I also have an idea that the best code (including comments) should be understandable to a reasonably intelligent person who is not familiar with the programming language. Some languages (Fortran, Python) make this easier than others (C++, Haskell). There is a good article here, discussing the "beauty" of some C++ code (although I disagree with his views on comments). I was struck by the discussion on how to write functions so that more information is provided to the reader of the code [4]. The example given is this:
int idSurface::Split( const idPlane &plane, const float epsilon,
idSurface **front, idSurface **back,
int *frontOnPlaneEdges, int *backOnPlaneEdges ) const;
Of course, if you are not familiar with the C++ *
, **
, and &
characters and the const
declaration, there is no information you can derive from this. It is complete gibberish. Modern Fortran, on the other hand, provides for the declaration of an intent
attribute to function and subroutine arguments. The equivalent Fortran version would look something like this:
integer function split(me,plane,eps,front,back,&
frontOnPlaneEdges,backOnPlaneEdges)
class(idSurface),intent(in) :: me
type(idPlane), intent(in) :: plane
real, intent(in) :: eps
type(idSurface), intent(out) :: front
type(idSurface), intent(out) :: back
integer, intent(out) :: frontOnPlaneEdges
integer, intent(out) :: backOnPlaneEdges
Here, it should be more obvious what is happening (for example, that plane
is an input and front
is an output). The use of words rather than symbols definitely improves readability for the non-expert (although if taken to the extreme, you would end up with COBOL).
References
- J. Raskin, "Comments are More Important than Code", Queue, Volume 3 Issue 2, March 2005, Pages 64-65.
- D. E. Knuth, "Literate Programming", The Computer Journal (1984) 27 (2): 97-111.
- F03/08 supporting Documentation tools, comp.lang.fortran.
- S. McGrath, "The Exceptional Beauty of Doom 3's Source Code", kotaku.com, Jan. 14, 2013.
Jan 29, 2015
The Standards of Fundamental Astronomy (SOFA) library is a very nice collection of routines that implement various IAU algorithms for fundamental astronomy computations. Versions are available in Fortran and C. Unfortunately, the Fortran version is written to be of maximum use to astronomers who frequently travel back in time to 1977 and compile the code on their UNIVAC (i.e., it is fixed-format Fortran 77). To assist 21st century users, I uploaded a little Python script called SofaMerge to Github. This script can make your life easier by merging all the individual source files into a single Fortran module file (with a few cosmetic updates along the way). It doesn't yet include any fixed to free format changes, but that could be easily added later.
Oct 26, 2014
The ISO_C_BINDING intrinsic module and the BIND
attribute introduced in Fortran 2003 are very handy for producing standard and portable Fortran code that interacts with C code. The example given here shows how to use the popen
, fgets
, and pclose
routines from the C standard library to pipe the result of a shell command into a Fortran allocatable string.
module pipes_module
use,intrinsic :: iso_c_binding
implicit none
private
interface
function popen(command, mode) bind(C,name='popen')
import :: c_char, c_ptr
character(kind=c_char),dimension(*) :: command
character(kind=c_char),dimension(*) :: mode
type(c_ptr) :: popen
end function popen
function fgets(s, siz, stream) bind(C,name='fgets')
import :: c_char, c_ptr, c_int
type (c_ptr) :: fgets
character(kind=c_char),dimension(*) :: s
integer(kind=c_int),value :: siz
type(c_ptr),value :: stream
end function fgets
function pclose(stream) bind(C,name='pclose')
import :: c_ptr, c_int
integer(c_int) :: pclose
type(c_ptr),value :: stream
end function pclose
end interface
public :: c2f_string, get_command_as_string
contains
!**********************************************
! convert a C string to a Fortran string
!**********************************************
function c2f_string(c) result(f)
implicit none
character(len=*),intent(in) :: c
character(len=:),allocatable :: f
integer :: i
i = index(c,c_null_char)
if (i<=0) then
f = c
else if (i==1) then
f = ''
else if (i>1) then
f = c(1:i-1)
end if
end function c2f_string
!**********************************************
! return the result of the command as a string
!**********************************************
function get_command_as_string(command) result(str)
implicit none
character(len=*),intent(in) :: command
character(len=:),allocatable :: str
integer,parameter :: buffer_length = 1000
type(c_ptr) :: h
integer(c_int) :: istat
character(kind=c_char,len=buffer_length) :: line
str = ''
h = c_null_ptr
h = popen(command//c_null_char,'r'//c_null_char)
if (c_associated(h)) then
do while (c_associated(fgets(line,buffer_length,h)))
str = str//c2f_string(line)
end do
istat = pclose(h)
end if
end function get_command_as_string
end module pipes_module
A example use of this module is:
program test
use pipes_module
implicit none
character(len=:),allocatable :: res
res = get_command_as_string('uname')
write(*,'(A)') res
res = get_command_as_string('ls -l')
write(*,'(A)') res
end program test
References
- C interop to popen, comp.lang.fortran, 12/2/2009.
Jul 08, 2014
I agree with everything said in this article: My Corner of the World: C++ vs Fortran. I especially like the bit contrasting someone trying to learn C++ for the first time in order to do some basic linear algebra (like a matrix multiplication). Of course, in Fortran, this is a built-in part of the language:
matrix_c = matmul(matrix_a, matrix_b)
Whereas, for C++:
The bare minimum for doing the same exercise in C++ is that you have to get your hands on a library that does what you want. So you have to know about the existence of Eigen or another library. Then you have to figure out how to call it. Then you have to figure out how to link to an external library. And the documentation is probably not that helpful. There are friendly C++ users for sure. It's just that you won't have a clue what they're telling you to do. They'll be telling you to set up a makefile. They'll be recommending that you look at Boost and talking about how great it is and you'll be all WTF.
And before you use that C++ library, are you really sure you won't end up with a memory leak? Do you even know what a memory leak is?