0

Im having trouble getting a function, that has to be recursive, to take a character and and return an integer array as result.

My example code:

program main
    implicit none
    integer :: i
    integer, dimension(3) :: myresult, rec_fun
    character(1) :: input

    input = 'B'
    myresult = rec_fun(input)
    do i = 1,3
        write(*,*) myresult(i)
    end do
end program main

recursive function rec_fun(input) result(a)
    implicit none
    character(1), intent(in) :: input
    integer, dimension(3) :: a 

    if (input == 'A') then
        a(1) = 2
        a(2) = 3
        a(3) = 4
        return
    else
        a = rec_fun('A') * 2
        return
    end if
end function rec_fun

The function rec_fun is supposed to take a character and give back an integer array. The output of the write loop in the main program should therefore be: 4 6 8

What does work is (integer -> integer), (character -> integer) and also (integer dimension(3) -> integer dimension(3)), which means the argument/return types dont need to be equal. However I need (character -> integer dimension(3)). But somehow taking a character and returning an array is not accepted and when trying to compile (gcc compiler with flag -lgfortran) I get

"Error: Array index at (1) must be of INTEGER type, found CHARACTER"

with (1) pointing to the first use of the function name in the main program in line 8. I don't know how to fix this is a way that is scalable and not hard coded, so that I could replace 3 with 1 Million. Workarounds using pointers etc won't work either, because array operations will be applied directly to the functions output on return. Does anyone have any ideas? Thanks.

EDIT: I find this question to be different, because it looks at the problem of array return and recursion within one function, plus neither of the suggested questions use the keyword "interface" in their solutions.

My solution, using an explicit interface, as suggested in the comments:

program main
    implicit none
    interface
        recursive function rec_fun(input) result(a)
            character(1), intent(in) :: input
            integer, dimension(3) :: a
        end function rec_fun
    end interface

    integer :: i
    integer, dimension(3) :: myresult
    character(1) :: input

    input = 'B'
    myresult = rec_fun(input)
    do i = 1,3
        write(*,*) myresult(i)
    end do
end program main

It compiles now and prints the correct results. However I'm not sure about how legit this solution is, since I never used fortran interfaces before.

P. Zeek
  • 43
  • 6
  • 1
    `integer, dimension(3) :: rec_fun` doesn't declare a function with array result, but a local variable. As the function you want to reference has an array result you must provide an _explicit interface_. About which there are many questions/answer. – francescalus Oct 16 '16 at 21:40
  • I visited http://fortranwiki.org/fortran/show/recursion to understand the architecture of recursive functions in fortran. This code declares `integer :: ack` local in the main program, which later becomes the ack-functions return value. Does that mean this only works with non-dimensial variables? How would an interface for rec_fun be implemented in my case? – P. Zeek Oct 16 '16 at 21:50
  • Yes, there are differences between functions returning scalar and array results. Searching for answers on explicit interfaces should tell you much of what you need to know, and there are also the [documentation](http://stackoverflow.com/documentation/fortran/2203/program-units-and-file-layout) [pages](http://stackoverflow.com/documentation/fortran/1139/usage-of-modules). – francescalus Oct 16 '16 at 22:02
  • Or put the regular module statements around the function. Put it on top of the program. Use the module in the program, and it should work also. Learning about modules is also good:) – Jonatan Öström Oct 16 '16 at 22:09
  • Also http://stackoverflow.com/questions/22520834/array-valued-function and http://stackoverflow.com/questions/6511711/computing-the-cross-product-of-two-vectors-in-fortran-90 and perhaps others. – Vladimir F Героям слава Oct 16 '16 at 22:14
  • *"plus neither of the suggested questions use the keyword "interface" in their solutions."* You still don't understand it, read them again. Modules are **the** way how to achieve explicit interface for your procedures. Interface blocks not good in your situation. Especially read thoroughly the links to documentation already pointed to you, http://stackoverflow.com/documentation/fortran/2203/program-units-and-file-layout – Vladimir F Героям слава Oct 16 '16 at 22:41
  • Good reading http://stackoverflow.com/questions/19781217/which-is-the-diffeence-between-an-interface-block-and-a-module-procedure-in-fort http://stackoverflow.com/questions/8412834/correct-use-of-modules-subroutines-and-functions-in-fortran – Vladimir F Героям слава Oct 16 '16 at 22:46

0 Answers0