Procedure Pointer, Passed-Objects - fortran

In the example available here, I try to define a type that has a procedure pointer component f. I also have the PASS option active, which means that the first argument of f is the passed-object argument.
In the program, f is associated with a subroutine called proc1, which changes the component i to 999. However, if I run the program, i is not changed and instead stays 123.
What is my mistake?
Thanks

I get an error when I try to compile that code. It goes away when I change the declaration of argument A in subroutine proc1 from type(derivedType) to class(derivedType).

I am not an expert, but I think that when you use the PASS attribute, you have to specify the argument that is being passed. At least that is the way I've been using it. for example
... pass(self) :: foo
function foo(self, baz) return(bar)
type(mytype), intent(in) :: self
real, intent(in) :: baz
...
Then the way to call this procedure would be: instanceOfMyType%foo(baz)
Cheers.

Related

Equivalence between declaring a function with data type or inside its body [duplicate]

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
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:
The function (result) was not given an explicit type, which lead to the compiler message shown.
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).
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.

How do variable declarations within types work in Fortran?

I'm trying to learn Fortran, and I've found that there aren't very many tutorials out there (probably due to it being an old language). The ones I have found are vague and undescriptive, and as I've gone into more complex things it has become harder and harder to guess what said tutorials are saying.My current issue is with creating types. The tutorial contains examples such as:
module m_shapes
implicit none
private
public t_square
type :: t_square
real :: side
contains
procedure :: area ! procedure declaration
end type
contains
! Procedure definition
real function area(self) result(res)
class(t_square), intent(in) :: self
res = self%side**2
end function
end module m_shapes
This compiles fine, so I know it works.
When I try to do something similar like this:
program type_test
implicit none
type :: thingy(a)
real :: a
end type
end program
It doesn't compile with errors like "The component at (1) that appears in the type parameter list at (2) has neither the KIND nor LEN attribute"
The tutorial I found does not explain types well enough, and I've tried things like real,kind :: a = kind(0.0), but to no avail. Does anybody know what's wrong?
Thanks in advance.
You did not explain, what you actually want to do. Or your words are not nearly clear enough. We can tell you why your attempt produces the error, but I have no idea what you actually want to do.
Perhaps you just wanted
program type_test
implicit none
type :: thingy
real :: a
end type
end program
without the (a)? That declares a simple type with one component. But hard to guess if this is what you wanted and what you tried with the (a).
It does not declare any variable with that type. That is done using
type(thingy) :: var
The syntax
type :: thingy(a)
real :: a
end type
attempts to declare a parametrized derived type. These types can depend on a kind or length parameter. These parameters must be integers. If it is a kind parameter, it allows to declare variables of the type with varying values of these parameters. Then the kind of some components of the type (you know what kind is, right? Fortran 90 kind parameter ) get their kind according to the value of the parameter. If it is a length parameter, it allows the length of some array or string components of the derived type to be parametrized - set during the variable declaration.
These parameters that appear in the parenthesis must be integer components and must have the kind or len attribute.
For example
type :: param_type(k,l)
integer, kind :: k
integer, len :: l
real(kind=k), dimension(l) :: array
end type param_type
type(param_type(kind(1.), 10)) :: o_sp_10
type(param_type(kind(1.d0), 20)) :: o_dp_20
The values of the parameters are set during the declaration of those o_sp_10 and o_dp_20 objects. I do not want to go into more details.

Why do the names of overriding arguments have to match those of the abstract interface?

Why do the names of arguments in overriding procedures need to match those of the abstract interface?
I understand that clearly the TYPE, INTENT, etc of such arguments are required to match the interface, but why should the compiler care what I call my variables?
In the following, I've defined a simple abstract utility class containing a single deferred procedure EVAL that takes a double precision argument.
!------------------------------------- an abstract utility class !
type, abstract :: func_1d
contains
procedure(interface_1d),deferred :: eval
end type func_1d
!-------------------------------------------- interface for eval !
abstract interface
function interface_1d(this,data) result(rval)
import :: func_1d
class(func_1d), intent(inout) :: this
real*8 , intent(in) :: data
real*8 :: rval
end function interface_1d
end interface
Defining an overriding class and an implementation for EVAL:
type, extends(func_1d) :: foo
contains
procedure, pass :: eval => eval_foo
end type foo
function eval_foo(this,another_variable_name) result(rval)
implicit none
class(foo), intent(inout) :: this
real*8, intent(in) :: another_variable_name
real*8 :: rval
!! etc
end function eval_foo
I get the following error from gfortran:
Error: Dummy argument 'another_variable_name' of 'eval' at (1) should be named 'data'
as to match the corresponding argument of the overridden procedure
If I instead substitute DATA for ANOTHER_VARIABLE_NAME everything compiles and runs as expected.
But this seems silly to me. I want to be able to inherit from FUNC_1D multiple times, and under various circumstances and being forced to call my variables DATA every time seems ridiculous.
I don't understand why the compiler should be interested in more than the TYPE and INTENT of the arguments?
Elaborating on High Performance Mark's comment
I don't know but I suspect that it may be down to Fortran's argument keyword capabilities, which mean that you can call your function like this fun_1d(data=the_data,this=that), that is you can name the arguments in the call rather than rely on position matching.
consider the following
type, extends(func_1d) :: foo
contains
procedure, pass :: eval => eval_foo
end type foo
type, extends(func_1d) :: bar
contains
procedure, pass :: eval => eval_bar
end type bar
with appropriate procedure definitions with interfaces
real*8 function eval_foo(this,foo_var)
class(foo), intent(inout) :: this
real*8, intent(in) :: foo_var
end function
real*8 function eval_bar(this,bar_var)
class(bar), intent(inout) :: this
real*8, intent(in) :: bar_var
end function
then later
class(func_1d), allocatable :: baz
allocate (foo_or_bar :: baz) ! For one of the types foo, bar
which, if any, makes sense with an argument keyword?
print*, baz%eval(data=s)
print*, baz%eval(foo_var=s)
print*, baz%eval(bar_var=s)
[There are cases where this would be much more pronounced, especially with optional dummy arguments.]
The standard requires that you keep the same dummy argument names (very likely to avoid the issue above). See 12.4.1 ISO/IEC 1539-1:2010:
12.4.1 Interface and abstract interface
The interface of a procedure determines the forms of reference through which it may be invoked. The procedure’s
interface consists of its name, binding label, generic identifiers, characteristics, and the names of its dummy
arguments. The characteristics and binding label of a procedure are fixed, but the remainder of the interface may
differ in differing contexts, except that for a separate module procedure body (12.6.2.5), the dummy argument
names and whether it is recursive shall be the same as in its corresponding separate interface body (12.4.3.2).
This states that separate procedures using the same interface shall have the same dummy argument names as the interface. This is further strengthened by 4.5.7.3:
The overriding and overridden type-bound procedures shall satisfy the following conditions.
- [...]
- Dummy arguments that correspond by position shall have the same names and characteristics, except for the type of the passed-object dummy arguments.

FORTRAN implicit cast when argument association happens in procedures

I am using fortran for a while, but I didn't check the implicit cast issue when using subroutines in fortran.
For example
subroutine printa(a)
double precision :: a
...
endsubroutine printa
When I called the subroutine
call printa(1)
I saw error #6633: The type of the actual argument differs from the type of the dummy argument. [1]
I know it is because I use an integer instead of a double precision as an input parameter. But I just realized that there is no implicit cast when using subroutines.
If I want a subroutine which handles integer and double precision data, it seems I have to define 2 subroutines for doing these things. Is there a way to make the implicit cast happen (just like the function calling in c)? Or there is another way to make it?
Thanks.
It is fundamental in Fortran that reals (including different precisions) and integers are different and that you need different subroutines to handle them. If you want the convenience of having a single call, similar to Fortran intrinsics such as sin which are implicitly several different functions, you can write the several different procedures and then create a generic interface to select between them. Fortran will then select the correct actual procedure based on the actual arguments, to match the dummy arguments. Here is an example that does it by rank of the array argument: how to write wrapper for 'allocate'. It can also be done, as you wish, by type of the argument.
You can overload a subroutine name so that when the "wrong" type of argument is supplied it is converted to right type and used to call the subroutine, as shown below.
module foo
implicit none
interface printa
module procedure print_int,print_real
end interface printa
contains
!
subroutine print_real(x)
real, intent(in) :: x
print*,"number is ",x
end subroutine print_real
!
subroutine print_int(i)
integer, intent(in) :: i
call print_real(real(i))
end subroutine print_int
!
end module foo
program main
use foo, only: printa
implicit none
call printa(1)
call printa(1.0)
end program main
Output:
number is 1.
number is 1.

Is it possible to disable named argument calling ?

I have two routines whose difference is only in the order of arguments, but I would like to use them through an interface, so that the proper one is invoked according to the order of the arguments when invoked. The compiler complains that it cannot distinguish them, and my guess is because if I use the syntax for named arguments at call, it won't know which one to call. One workaround would be to use different names for the arguments, but I was wondering if there's a way to disable named argument call style.
Example, this is the situation I am trying to handle
module Foo
interface Bar
module procedure Bar1
module procedure Bar2
end interface
contains
subroutine Bar1(i,r)
integer, intent(in) :: i
real, intent(in) :: r
print *, "bar1"
end subroutine
subroutine Bar2(r,i)
real, intent(in) :: r
integer, intent(in) :: i
print *, "bar2"
end subroutine
end module
program fuux
use Foo
integer :: i
real :: r
r = 5.0
i = 3
call Bar(i,r) ! note that if I call Bar(i=i, r=r) the compiler cannot disambiguate
! so it will complain at the interface statement
end program
I do not know of any way to do what you suggest, or rather to do what I think you are suggesting in the phrase 'disable named argument call style'. If this answer infuriates, disappoints or displeases in any way, post some code and we (SO I mean, I have not too many airs and graces and rarely use the royal 'we') might be able to suggest a cunning trick which will please you.
EDIT
No direct way to do what you want to do springs to mind. The first workround that occurs to me is to define a subroutine called bar which takes the series of arguments in a canonical order and simply calls bar1, bar2 (and any other baby bars you care to define) with the arguments in the appropriate order.