14

I am trying to learn to work with functions. I have the following code:

program main
  implicit none

  write(*,*) test(4)
end program

integer function test(n)
  implicit none
  integer, intent(in) :: n
  integer :: i, ans

  ans=1
  do i=1,n
  ans=ans*i
  enddo

  test=ans
end function test

When I compile (with gfortran 4.1.2), I get the following error:

In file test.f90:4

  write(*,*) test(4)
           1
Error: Function 'test' at (1) has no IMPLICIT type
Ian Bush
  • 6,996
  • 1
  • 21
  • 27
sodiumnitrate
  • 2,899
  • 6
  • 30
  • 49

4 Answers4

19

Move the line

end program

to the end of your source file and, in its place, write the line

contains

As you have written your program it has no knowledge of the function test, which is what the compiler is telling you. I have suggested one of the ways in which you can provide the program with the knowledge it needs, but there are others. Since you are a learner I'll leave you to figure out what's going on in detail.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
11

Just in case, someone has the same problem an alternative way (especially for the case discussed in the comment) is to add

integer,external :: test

after

implicit none

in the main program.

PeMa
  • 1,559
  • 18
  • 44
  • 3
    The accepted answer is MUCH better, because it provides the explicit interface and enables checking of the argument types. – Vladimir F Героям слава Mar 28 '14 at 13:14
  • 1
    'better' ... well, for a beginner this solution is just easier and thus also better, in a sense. It doesn't require additional knowledge about concepts like modules or contains. Of course the accepted answer is more elegant and save. So I totally agree in the sense that I'd prefer it for my programs. But as a beginner I was always grateful for simple solutions, even though they might not solve the problem in the most general way. – PeMa Mar 28 '14 at 13:37
  • 4
    I don't agree. You are guiding the beginners to the area where they can be trapped with the old style that was abandoned for good reasons 20 years ago. When I teach Fortran programming at our university, the program organization and modules is one of the first and most important things. I don't show how to write a subroutine before introducing a module as a container where to place them. – Vladimir F Героям слава Mar 28 '14 at 14:21
  • It's good that you do it like this. But not all the available literature goes your way. And obviously the tutorial used by the questioner didn't. I don't know how someone can be 'trapped' in a style, I didn't, even though I started with fortran 77 (which is still worth knowing in the scientific world). Both solutions are working and have advantages and disadvantages. In either way you should know what you are doing. The rest is just personal taste of how one should learn fortran and that's off topic in this forum. – PeMa Mar 28 '14 at 15:12
  • 3
    Sorry to come late to the fight ... the use of `external` effectively disables the compiler's ability to check that procedure calls correctly match actual and dummy arguments. Unequivocally, and objectively, 'better' in the sense of making it more difficult for a programmer to write unsafe, or even just plain wrong, code. – High Performance Mark Apr 22 '15 at 13:17
  • I wouldn't call this a fight. We all know why `external` is dangerous and everyone is happy about the new standard. Nevertheless a lot of subroutines written in Fortran 77 still exist and are heavily used. Since the OP learns Fortran, he should also know how to use these routines. I think you agree that it's a bit too time consuming and also not failsafe to first rewrite complete libraries, before using them. In this case it's definitly 'better' to know about `external`. And by the way, I hate it each time that I'm forced to use it, but sometimes you can't rebuild the house before you move in. – PeMa Apr 22 '15 at 17:50
  • 2
    ... and I don't get why people downvote correct answers! – PeMa Apr 22 '15 at 17:56
6

Another simple way, not mentioned in the current answers:

Move the function before the main program, put module subs, implicit none and contains before the function and end module after the function. The put use subs into your program.

This way the program can see everything necessary ("explicit interface") about the procedures in the subs module and will know how to call them correctly. The compiler will be able to provide warnings and error messages if you try to call the procedures incorrectly.

module subs
  implicit none
contains
  integer function test(n)
    !implicit none no longer necessary here
  end function test
end module

program main
  use subs
  implicit none
3

Just put this:

program main
  implicit none

integer test

  write(*,*) test(4)
end program
...

You need to declare the function as a variable for the compiler to know the return type of the function.

renedet
  • 287
  • 3
  • 12