5

Well, let me say first why I want to do this. I frequently write code in C/C++, so for me it's very natural to define functions like:

vector<int> TestFunct (int a, int b){
<some code here>

return <result>;}

Now I'm learning Fortran, so I declare functions like this:

function TestFunc(a,b)
        integer, dimension(:)    :: TestFunc
        integer                  :: a
        integer                  :: b
        <some code here>
endfunction TestFunc

But I recently learned that the data type of the result can be defined in the function statement, like: <data_type> function TestFunc(a,b), which is much more natural for me, because I'm used to the similar C++ declaration.

The issue is that, when I', trying to define a vector (actually a integer, dimension(:), strictly talking) as the result data type, I have the ifort error #5082 (I will detail it in the next lines).

In an example, for the code:

real, dimension(:) function TestFunc(a,b)
         integer, intent(in)    :: a
         integer, intent(in)    :: b

         <more code here>

endfunction Testfunc

I get the output:

main.f90(23): error #5082: Syntax error, found ',' when expecting one of: ( * ) ( :: %FILL , TYPE INTEGER REAL COMPLEX BYTE CHARACTER CLASS DOUBLE ...
real, dimension(:) function TestFunc(a, b)
----^
main.f90(23): error #5082: Syntax error, found IDENTIFIER 'FUNCTION' when expecting one of: * :: , <END-OF-STATEMENT> ; [ / = => WITH
real, dimension(:,:) function TestFunc(a, b)
---------------------^

Hope I had clearly explained my issue.

EDIT: So, in order to sum up what I just said in one question: How I declare a vector (i.e.:integer, dimension(:)) as the returning data type in the function statement?

vaultah
  • 44,105
  • 12
  • 114
  • 143
Alfonso Santiago
  • 531
  • 4
  • 20
  • I'm not sure what the question is. Is this what you want to do: http://stackoverflow.com/questions/8264336/how-to-get-priorly-unkown-array-as-the-output-of-a-function-in-fortran. Or maybe this is what you need: http://stackoverflow.com/questions/3828094/function-returning-an-array-in-fortran – M. S. B. Oct 04 '13 at 19:13
  • I think he is asking how to specify the shape and size of the function return value (i.e. `DIMENSION(:)`) in the `FUNCTION` statement, that is, on the same line. – milancurcic Oct 04 '13 at 19:15
  • Not exactly. I do want to return an arbitrary length vector from the function, but, also, I want to declare the data type in the function statement. I mean, I can declare `real function TestFunc(a,b)` but I can't (at least I didn't found a way yet) declare `real, dimension(:) function TestFunc(a,b)`. Instead of that, I have to declare it like this: `function TestFunc(a,b); real, dimension(:) :: TestFunc; <...morecode...>`. – Alfonso Santiago Oct 04 '13 at 19:21
  • OK, you cannot do that, see Vladimir F's answer below. – milancurcic Oct 04 '13 at 19:22

2 Answers2

7

You can define the return type before the function symbol, but it is limited. It is an older way meant only for simpler cases. The rules are somewhat obscure and I do not remember them by heart, but here is what the standard says:

The type and type parameters (if any) of the result of the function defined by a function subprogram may be specified by a type specification in the FUNCTION statement or by the name of the result variable appearing in a type declaration statement in the specication part of the function subprogram. They shall not be specified both ways. If they are not specied either way, they are determined by the implicit typing rules in eect within the function subprogram. If the function result is an array, allocatable, or a pointer, this shall be specied by specifications of the name of the result variable within the function body. The specifications of the function result attributes, the specification of dummy argument attributes, and the information in the procedure heading collectively define the characteristics of the function (12.3.1).

1

Yes, you cannot define an arbitrary shaped function in that manner. You need to specify its length, the easiest way is to send its length as an extra parameter:

function testFunc(n, a, b)
   integer, intent(in) :: n,a,b
   real, dimension(n) :: testFunc
   <...stuff...>
end function testFunc

Alternatively, you can do what you want as a subroutine:

subroutine testSub(a, b, F)
   integer, intent(in) :: a, b
   real, dimension(:), intent(inout) :: F
   <...stuff...>
end subroutine testSub

in which you'd invoke this via call testSub(a, b, F).

Kyle Kanos
  • 3,257
  • 2
  • 23
  • 37
  • That's right, you can make argument passing to the main program with a dummy variable defined inside the subprogram. But, what you had said, actually does not answer my question. I didn't wanted to go further in my example, but I need to do it with a function (not a subroutine) because in that way, I can overload an operator with `interface operator (); module procedure TestFunc; end interface;`. – Alfonso Santiago Oct 04 '13 at 17:01
  • You do not actually have a question in your OP (at least I do not see any question marks there). I assumed your question is "How can I get an arbitrary-length vector result from a function?" and answered accordingly. If this is not what you had in mind as a question, perhaps you could state your true question? – Kyle Kanos Oct 04 '13 at 17:08
  • Just edited the post to clarify this misunderstood. But, actually, I keep thinking that just the title of the post in enough to understand that I'm talking about **defining the result datatype** in the **function statement**. – Alfonso Santiago Oct 04 '13 at 17:32
  • 2
    Your question is precisely what I assumed it was: how do you define an *arbitrary*-length vector from a function. The answer is: you cannot, you **need** to specify the length. – Kyle Kanos Oct 04 '13 at 17:56
  • What you could do (at least with Fortran 2003 and above), is to pass an `allocatable` array to a `subroutine` and allocate it there. With Fortran 90/95 you could something similar using pointers. Not exactly what you asked for, though. – Alexander Vogt Oct 04 '13 at 19:17