Reputation: 30424
I'm struggling with a concise title, but it's not that complicated. I have a function that returns a structure (derived type) and I'm looking for a simple way to reference only a part of the structure while calling the function (without copying/pointing to another structure).
program main
real :: xx = 1.
real :: yy = 2.
! works fine but what I want is to be
! able to return %tx and %ts separately
print *, " tax ", tax(xx,yy)
! just guessing at possible syntax here, but neither works
print *, " tax ", tax%tx(xx,yy)
print *, " tax ", tax(xx,yy)%tx
contains
function tax(x,y)
real :: x, y
type tTax
real :: tx, ty
end type tTax
type(tTax) :: tax
tax%tx = x * 100.
tax%ty = y * 100.
end function tax
end program main
I'm restricted to f90/f95 feature set but feel free to include f2003 answers also.
And I'm really looking for something simple here, if it exists. Otherwise, it's just going to be better to do as a subroutine (if the alternative is keeping it as a function but adding pointers, interfaces, etc.).
I also tried having the function return a 2 dimensional array instead of a structure and had the same basic problem -- it works, but I am only able to print the whole array, not any array sections by themselves.
I had trouble even guessing at the syntax there since ()
is used for both functions and array sections in fortran (as opposed to languages like python which uses []
for indexing, so it's fairly natural to mix functions and indexes e.g. something like tax(xx,yy)[1,:]
).
Upvotes: 2
Views: 1510
Reputation: 60008
The problem is not in the parenthesis symbols, it is just whether you are allowed to reference a component or element of an expression or not.
And in Fortran you are not allowed that. You can only use the % syntax or array indexing () on variable or constant names or on associate-names.
Upvotes: 3
Reputation: 593
You can create a user-defined constructor by overloading the derived-data type's name with a function return.
Liberal use of the Fortran 2003 standard's associate
construct allows one to access specific type-components without copying or resorting to memory-leak-prone pointers.
Is there any particular reason why you're restricting yourself to Fortran 2003; a great deal of Fortran 2008 is supported by most popular compilers.
The following code
module mymod
! Explicit typing only
implicit none
! Declare derived data type
type tTax
real :: tx, ty
end type tTax
! User-defined constructor
interface tTax
module procedure tax
end interface tTax
contains
function tax(x, y) result (return_value)
real, intent (in) :: x, y
type (tTax) :: return_value
return_value%tx = x * 100.0
return_value%ty = y * 100.0
end function tax
end module mymod
program main
use mymod
! Explicit typing only
implicit none
real :: xx = 1.0, yy = 2.0
type(tTax) :: foo
print *, " tax ", tax(xx,yy)
print *, " tax ", tTax(xx, yy)
! Invoke the user-defined constructor
foo = tTax(xx, yy)
! Fortran 2003's associate construct
associate( &
tx => foo%tx, &
ty => foo%ty &
)
print *, " tax ", tx, ty
end associate
end program main
yields
gfortran -Wall -o main.exe mymod.f90 main.f90
./main.exe
tax 100.000000 200.000000
tax 100.000000 200.000000
tax 100.000000 200.000000
Upvotes: 3