3

Below is a sample code that addresses the problem I am having. The error message I am getting is

Function result 'sample' at (1) has no IMPLICIT type.

I label where line (1) is below.

I tried to follow this other question, however I wasn't able to figure it out. This function is within a module in my program and I made sure that the module has contains and I end the module after this function.

I also use implicit none in this function so I'm not sure why I get this message. How can I fix this error message?

Adding Real or Complex in front of function works, but I don't really get why. Shouldn't I only be able to use complex since the arrays are complex inside the function? Which is more suitable for my actual function? Both yield no compilation errors.

real function Sample(func)   !this is line (1)
!complex function Sample(func)

implicit none

integer :: n,m
real :: x,y
complex, dimension(-9:9,-9:9), intent(in) :: func
complex, dimension(-9:9,-9:9) :: LocalF

LocalF = func

do n=-9,9
do m=-9,9

    x = real(n)*0.2
    y = real(m)*0.2
    LocalF(n,m)= cmplx(z1(x,y),z2(x,y)) !assume z1,z2 are well defined

end do
end do

end function Sample
Community
  • 1
  • 1
Jeff Faraci
  • 403
  • 13
  • 28
  • Do you have `implicit none` at the beginning of your program? – M-- May 03 '17 at 19:41
  • @Masoud Yes it is in my function above. Is that what you mean? Or do you mean implicit none in the module or in the Main program itself? – Jeff Faraci May 03 '17 at 19:41
  • **main program!** I can see that you have it in your function (which I have never done it for debugging!!!). – M-- May 03 '17 at 19:44
  • When you say module has `contains` you mean at the end of the module and before your subroutines and functions. Right? I know these are basic. Don't get offended. – M-- May 03 '17 at 19:47
  • 1
    @Masoud No problem at all I'm pretty new to fortran so feel free to ask basic stuff. Thanks. I have implicit none in the main program, Yes. And yes to your other question, my module has 'contains' at the end and before my subroutines and functions. – Jeff Faraci May 03 '17 at 19:53
  • You haven't declared the type of the function result, called `Sample`, in the function. See [this documentation](http://stackoverflow.com/documentation/fortran/1106/procedures-functions-and-subroutines/3553/function-syntax) for details. – francescalus May 03 '17 at 20:12
  • @francescalus: yes, I was just checking the documentation out too. Sadly, I don't think it really answers the question. And I'm struggling to find a good duplicate too. – High Performance Mark May 03 '17 at 20:21
  • Do you mean, @HighPerformanceMark, that the problem is something else, or that there's a misunderstanding about how functions work? [That is, even with `sample` declared there's no value setting.] – francescalus May 03 '17 at 20:27
  • I mean that I think the documentation is poorly structured to introduce the necessary details of how to define a function in a way that is easily digestible by a beginner. – High Performance Mark May 03 '17 at 20:33
  • @francescalus Thanks, I added 'real' in front of function and it worked. THen I also tried adding 'complex' in front of function and that also worked. However I'm not really sure I understand much of that documentation...But i'm confused, which should I actually use? The arrays defined in this function are complex (so I think Complex?) (Realistically, this function is calculating just the boundary and initial conditions for the function in my code). I updated my post to address my question. – Jeff Faraci May 03 '17 at 20:39
  • @HighPerformanceMark Thanks you're indeed correct I'm having some trouble digesting any of it. However, I'm trying to make some sense out of it still. Also, I tried to follow your answer on the post that I linked in the question but still have the problem so I guess its elsewhere. Also, I updated my post now. – Jeff Faraci May 03 '17 at 20:42
  • dont you also get a warning about not setting a return value? – agentp May 03 '17 at 23:40
  • @agentp no I don't, I just followed what HighPerformanceMark suggested below. He's probably a better person to ask than me...(if you're referring to using real function or complex function; that also gave me no error message. However I'm using what HighPerformanceMark suggested below) – Jeff Faraci May 03 '17 at 23:41

2 Answers2

5

In Fortran every function has a result. If you like you can think of the result as a value returned by the function. Like every other value in a Fortran program a function result has a type, and a kind and a rank too.

By default the function result has the same name as the function itself, and its declaration is prepended to the function declaration. For example, here

integer function add(m,n)
    integer, intent(in) :: a,b
    add = a+b
end function

the function is called add and you can see (a) that the result is of type integer (and of default kind and scalar) and (b) that the result is formed by adding the two arguments together.

For functions returning arrays this syntax is not available, so you couldn't write something like

 integer(1:4) add_vec(m1,m2)

In such cases you have to explicitly define the name (and later type and kind) of the result variable. Sticking with the simple example, something like

   function add(m,n) result(addvec)
        integer, intent(in) :: a(4),b(4)
        integer, dimension(4) :: addvec
        ....
    end function

Notice that you don't define the intent of the result.

In OP's case sample is, I think, intended to return a rank-2 array of complex values. I think OP needs to replace

function Sample(func)   !this is line (1)

with

function Sample(func)  result(LocalF)

and see how that goes. Here, if it is not evident already, you learn that the result name doesn't have to be the same as the name of the function.

Furthermore ... Adding Real or Complex in front of function works, but I don't really get why.

It might work in the sense of compiling, but executing it will lead to tears. By telling the compiler that the function result is either a real or complex value you satisfy the syntactical requirements for a function definition. But without assigning a (real or complex as declared) value to the result variable (called Sample in OP's code) the function will, at best, return junk.

To be as clear as I can ... in OP's original code there were two serious mistakes:

  1. The function (result) was not given an explicit type, which lead to the compiler message shown.
  2. The function did not include setting the value of the result variable, i.e. the variable with the same name as the function (in the absence of the result clause).
High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
  • Thank you. Adding 'result(LocalF)' worked. Based on the example you provided first using 'integer function ...', Can I also use 'Complex Function Sample(func)'? I tried both 'Complex Function Sample(func)' and 'Real Function Sample(func)' (without using Result(LocalF)) and both worked for me. Why is that though? Wouldn't only Complex Function be suitable here? – Jeff Faraci May 03 '17 at 20:54
  • So where do you suggest asking them then and whats the comment section for exactly? I already updated the post addressing the question I mentioned in the comment. Thanks! – Jeff Faraci May 03 '17 at 21:05
  • Thanks for the updated answer, I didn't get notified for some reason. This is very helpful. – Jeff Faraci May 06 '17 at 16:40
1

Procedures in Fortran come in two types: functions and subroutines. This question is about functions, so I'll consider just those.

What was missing in the first revision, giving the error about the implicit type of the function result1, was the result type.

Adding real function ... or complex function ..., etc., resolves that problem by explicitly giving the type of the function result. The linked documentation gives other ways of doing that.

The function's result is used when the function is referenced. When we have a reference like

func0 = Sample(func)

in the main program, the function Sample is invoked and the function result is defined in its execution. At the end of the function's execution its result is placed in the expression of the reference.

So, if you declare

real function Sample(func)

or

complex function Sample(func)

what you are saying is that the function result is either a real or complex entity. And when the function is evaluated, whatever value Sample had at the end is used in the expression (here assignment).

As a consequence of the function result being returned through Sample (in this case) we need to define its value. The important thing to note for the question, then, is that LocalF is a variable local to the function. If you mean it to be the result of the function you need to use the function result.

You have a number of options:

function Sample(func)
  <type>, <attributes> :: sample  ! Instead of LocalF
  ...                  :: func
end function

or

function Sample(func) result(LocalF)
  <type>, <attributes> :: LocalF
  ...                  :: func
end function

You can even have

<type> function Sample(func)
  <attribute statements for Sample>
  ... func
end function

but I really suggest you avoid that last one.


1 Note the error here is about type for the function result; in the linked question simply about the function when referenced.

Graham
  • 7,431
  • 18
  • 59
  • 84
francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Thanks a lot, I already marked the answer above as the answer so I can't mark this one too. Sorry about that. I'm not entirely sure of the procedures on this site and I don't want to tick anybody off. This does answer my question clearer though than the answer above (since you address real function, complex function, etc). I'm trying to learn fortran from Chapman's book also but I find you to be teaching me it clearer. Thanks for all of the help always. – Jeff Faraci May 03 '17 at 21:08
  • Based off your answer: Correct me if I'm wrong but, I think I need to use the function 'result' since I need to use this LocalF elsewhere in my module (in another subroutine, etc). So I think that I should use result(LocalF). I do not think I should use real/complex function since I don't want it to just be local to the function. This LocalF is the initial condition of my differential equation, so when I solve the differential equation in my other subroutines etc, I need to use it. – Jeff Faraci May 03 '17 at 21:14
  • You may need to ask a separate question about that, as it would be too much to detail in answers here. However, in short: neither approach would work. Loosely, both local variables in a function and the function result only exist whilst the function is being executed (or in the immediate.expression referencing it). – francescalus May 03 '17 at 21:28
  • To your first comment, I actually find the other answer more readable (to the extent that I wouldn't have replied had I not been part way through this when that answer was posted) - but then I also understand both. In terms of which answer you accept, that's entirely up to you. You can unaccept any question you accept, even without accepting another (and you don't even have to accept one in the first place). An accepted answer just means "this is the one I found best answered my question". It needn't be first, and it needn't even be "right" or useful to anyone else. – francescalus May 03 '17 at 21:32
  • okay thank you for that clarification. That's a good point not to accept any answer too quickly, makes sense. Both answers are very helpful to me. – Jeff Faraci May 03 '17 at 21:34
  • Random question, if not appropriate for this site I understand and apologize in advance. Do you provide 1 on 1 tutoring in fortran via skype or however else? If so I am very interested and I use paypal or whatever other methods you're comfortable with. – Jeff Faraci May 06 '17 at 19:28