Questions about statement functions

Fast question. I just got to read a code where a function was defined as in the following example:

program fexps
  implicit none
  real :: fexp, x
  fexp(x) = exp(x+1)
  print'(":: exp(x)  = ",g0)', exp(3.0)
  print'(":: fexp(x) = ",g0)', fexp(2.0)
end program fexps

I just got a bit shock because, as far as I can remember, is the first time I see this and I think I haven’t read this in any book I’ve read on Fortran. I would always go to define the function as function fexp ....

  1. Can anyone explain what is happening here behind the scenes (pointer associations, etc.)?
  2. Would that work with other user-defined function?
  3. How much would you recommend to use this approach, or would you encourage people to avoid it and why?
1 Like

It took me a bit of time to realise that you are not dealing with a brandnew and undocumented feature here, but with an old feature that has been known to cause trouble: statement functions. Internal functions are the newer and safer and much more capable replacements. Basically, such a statement function consists of a single statement like the one you showed. It could also be:

fexp(x,delta) = exp(x + delta)

(or any variation on that theme)

1 Like

Great! Thanks a lot @Arjen. Forgot to mention that I’ve partially read the books… Now I see in my reference book (Moder Fortran Explained, Metcalf, Reid, Cohen) in section B.1.5 that it appears as an obsolescent feature in the Fortran 95 standard.

So do we agree that it’s something to be avoided?

1 Like

Well, I definitely agree. It is rather compact, that is the attractive bit, but it has caused confusion in the past to both human beings and compilers. You would be far better off with a proper internal function. Or something defined in a separate module :wink: .

2 Likes

I agree. I really prefer and like to define a local functions within the scoping unit after the contains statement. But yeah, quite attractive because of its simplicity.

1 Like

In the F77 era, when there were no smartphones and, incidentally, no internal or module functions, the statement functions were quite useful. Containing just a single expression as their definition, could be treated as an obvious hint to the compiler to inline them in the code. Probably could have been still such a hint, if not made obsolescent.

1 Like

Statement functions have been obsolescent in the standard for some time now. Enabling standards conformance diagnostics would pick that up.

2 Likes

I was just pondering if statement functions could be resurrected in some other form like this:

module test
    use iso_fortran_env, only: wp => real64 
    implicit none
    contains 
    real(wp), function :: fexp(real(wp),intent(in) :: x, real(wp),intent(in) :: delta) = exp(x + delta)
    !...etc...
end module test

I see the advantage of having a way to define simple functions with one-liners. Just an idea.

1 Like

A CONTAIN’ed function should work as well as statement functions, with the ability to better define the argument list.

Defining the arguments that appear in an existing statement function can be confusing. I now prefer contained functions for their clarity of variable definition.

The more confusing (annoying?) issue with both is the scope of the defined function and also the scope of variables referenced in either function type.

Many years ago, I did like statement functions as I thought they had a more efficient argument list implementation, but these impressions are hard to justify.

1 Like