Search code examples
functionfortranfortran90rank

Rank mismatch in function result


I am learning to program in fortran and was making a basic program. In it I am trying to return an array from a function in my program, which is resulting in this error: Interface mismatch in global procedure 'test1' at (1): Rank mismatch in function result (0/1).

Below is a reconstruction of the error:

program Test
    implicit none
    integer :: a
    interface
        function test1(n) result (m)
            integer :: n
        end function test1
    end interface

    a = test1(4)

end program Test

function test1(n) result (m)
    implicit none
    integer :: n, m(2)
    m(1) = n**2
end function test1

The error is after the interface statement at function test1(n) result (m).

Since I am new to fortran, I assume I have missed something basic so any help is appreciated.


Solution

  • The interface and implementation of test1 have mismatched arguments, and a is mismatched to the result of test1. If you declare a to be an array of length 2 and add a declaration of m to your interface to also be an array of length 2, then everything should work:

    program Test
       implicit none
       integer :: a(2)
       interface
           function test1(n) result (m)
               integer :: n, m(2)
           end function test1
       end interface
    
       a = test1(4)
       write(*,*) a
    
    end program Test
    
    function test1(n) result (m)
       implicit none
       integer :: n, m(2)
       m(1) = n**2
    end function test1
    

    Declaring functions

    Declaring functions in the global scope and calling them through an interface will lead to a lot of excess code writing and maintenance. There are two better ways to declare functions; as internal functions, or in a module.

    If you're writing a short program, you can get away with putting your functions directly inside your program, using contains. This gets rid of the need for an interface entirely:

    program Test
       implicit none
       integer :: a(2)
    
       a = test1(4)
    contains
       function test1(n) result (m)
          integer :: n, m(2)
          m(1) = n**2
       end function test1
    end program Test
    

    note that I've dropped the implicit none from the function, as it's now inherited from Test.

    If your code gets a bit bigger, you will want to declare your functions in separate modules, as:

    module test_module
       implicit none
    contains
    function test1(n) result (m)
       integer :: n, m(2)
       m(1) = n**2
    end function test1
    end module
    
    program Test
       use test_module
       implicit none
       integer :: a(2)
    
       a = test1(4)
    end program Test