I would like to pass an elemental procedure to another elemental procedure. A minimum working example might be something like this:
elemental real function func(x, f_dummy)
implicit none
real, intent(in) :: x
interface
elemental real function f_dummy(x)
real, intent(in) :: x
end function f_dummy
end interface
func = 2.0 * f_dummy(x)
return
end function func
The compiler says:
Error: Dummy procedure ‘f_dummy’ not allowed in elemental procedure ‘func’ at (1)
If I delete all instances of elemental, then it compiles.
Is there a legal way to pass an elemental procedure to another elemental procedure?
No, the arguments of an elemantal procedure must be scalars, not arrays, not procedures. As a workaround you can write a procedure that deals with an array and the procedure and is just pure, not elemental.
Elemental procedures can be dummy arguments. But an argument of an elemental procedure cannot be a procedure. Perhaps it could be a procedure pointer, but then you would have to pass an array of pointers when calling it elementally on an array.
Related
If I have an allocatable array of a finalizable derived type, will the finalizer be called on every individual element when the array goes out of scope?
Here is a small code example that illustrates the question:
module LeakyTypeModule
implicit none
private
type, public :: LeakyType
real, pointer :: dontLeakMe(:) => null()
contains
procedure :: New
final :: Finalizer
end type
contains
subroutine New(self, n)
class(LeakyType), intent(out) :: self
integer , intent(in) :: n
allocate(self%dontLeakMe(n))
self%dontLeakMe = 42.0
end subroutine
subroutine Finalizer(self)
type(LeakyType), intent(inout) :: self
if (associated(self%dontLeakMe)) deallocate(self%dontLeakMe)
end subroutine
end module
program leak
use LeakyTypeModule
implicit none
type(LeakyType), allocatable :: arr(:)
allocate(arr(1))
call arr(1)%New(1000)
deallocate(arr)
end program
Note that this program leaks the dontLeakMe array allocated in the New() method of LeakyType. At first this was a bit surprising for me but, then I discovered that the problem can be fixed by declaring the finalizer elemental. Both gfortran and ifort behave in the same way, so I assume this behaviour is following the Fortran 2003 standard.
Can anyone confirm this? To be honest I have a hard time time understanding what the standard says on this particular point.
Right now I also can't see much use in not declaring all my finalizers elemental. Does this have any application I'm overlooking?
The rules for determining whether a final procedure is invoked, and which final procedure is invoked, are the same as for resolution of generic procedures in terms of rank matching requirements.
Noting that the question is tagged Fortran 2003...
Elemental procedures in Fortran 2003 and prior have to be PURE. If your finalizer needs to do something that is incompatible with the pure attribute (which is reasonably common) then the finalizer cannot be elemental, and you need to write the rank specific variants.
Fortran 2008 introduces the concept of IMPURE ELEMENTAL, which is quite handy for writing finalizers.
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.
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.
I had a question about the correct way of programming user-defined operators in Fortran. To be more specific, I will provide the example of my problem. I am working on creating a user-defined data type for spherical particles called 'Particle'. I want to define an operator that takes an existing array of Particle objects and adds a new Particle object to it. I was wondering how I would go about defining user defined operators to do such an action.
Currently I have, within the type definition for Particle, the following lines:
procedure, public:: addNewParticleTo
generic:: operator(.spawn.) => addNewParticleTo
Following which, I have a subroutine that is defined as follows:
subroutine addNewParticleTo(a_LHS, a_RHS)
implicit none
class(Particle), dimension(:), allocatable, intent(in):: a_LHS
class(Particle), dimension(:), allocatable, intent(inout):: a_RHS
<rest of the code>
end subroutine addNewParticleTo
I intend for the operator to be invoked as:
particle .spawn. particleArray
I was wondering if this is the correct way to go about doing this. Any suggestions or advise on this will be very helpful.
To expand on the comments, you will need to have the operator code as a function. Further, each input would need to be intent(in). This would indeed allow something like array = particle .spawn. array.
However, another change is required to your subroutine: one of your arguments should be a scalar. [The first, unless you play with the pass attribute.]
function addNewParticleTo(A, B) result(C)
class(particle), intent(in) :: A
class(particle), allocatable, intent(in) :: B(:)
class(particle), allocatable :: C(:)
! ... code to do the appending
end function
Finally, my advice is that having this as a type-bound operator is making things quite complicated, with the polymorphism and so on. Also, array = particle .spawn. array seems very unintuitive.
Instead, just a plain subroutine so that call add_to_particle_array(all_particles, new_particle) works seems cleaner. This is closer to your original code, but doesn't answer your question about operators, alas.
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.