I'm fairly new to Fortran, and while going through some documentation it seems like both subroutines and functions can use the 3 types of parameter intent:
But when trying to implement intent (inout) in a function something similar to the snippet shown below
function cell_blocked(row,col,ncb) result (ncb)
integer, intent(in) :: row,col
integer, intent(inout):: ncb
if (row == col) then
ncb = ncb + 1
end if
end function cell_blocked
I get the following compiler error:
Symbol 'cell_blocked' at (1) has no IMPLICIT type
ncb is a counter that I would like to pass into the function and update given a condition and return the value.
If I try this with a subroutine I don't get any compiler errors, so I'm confused why the error while using a function
You are quite correct that each of the three intents (or using no intent) can be specified for any dummy argument of a function, just as they can for a subroutine.
However, the dummy arguments for a function are still quite distinct from the function result. The result(ncb)
clause here is not saying "the argument ncb is the result of my function". Instead result(ncb)
says "the result of the function is called ncb instead of cell_blocked".
You cannot give the function result the same name as one of the function's arguments. (You get an (unhelpful) compiler error saying that cell_blocked
is not given an implicit type because the result clause is invalid, so the compiler is ignoring it and considering the function result to be called cell_blocked
. A more helpful error message would include the fact that the result clause is itself invalid.)
The function result is a completely separate thing from any of the dummy arguments, and having a function result is what distinguishes a function from a subroutine. You may (whether it's advisable or not) change a dummy argument (intent(inout)
, intent(out)
or no intent) independently of how you specify the result of the function.
Given the function
function f(a, b, c, d)
integer, intent(in) :: a
integer, intent(out) :: b
integer, intent(inout) :: c
integer :: d
integer :: f ! Function result unless there's a result clause
...
f = ...
end function f
the function result is f
and the function result is used in the expression in the right-hand side of the assignment
y = f(a, b, c, d)
The value of the function result is whatever was assigned to f
by the end of the function's evaluation. Not one of the dummy arguments, however modified, is a "result".
In the function of the question (which is perhaps better left as a subroutine) we are failing to give the function's result a value. If we want the function's value to be either ncb
or an incremented version of that we don't use an intent(inout)
dummy to do that:
function cell_blocked(row,col,ncb)
integer, intent(in) :: row,col, ncb
integer :: cell_blocked
! One of many ways writing this logic
if (row == col) then
cell_blocked = ncb + 1
else
cell_blocked = ncb
end if
end function cell_blocked
You may then write something like
ncb = cell_blocked(row, col, ncb)
but one then wonders whether a subroutine is what was wanted all along.