Re: Reference to derived type element by index?



Rob Crain wrote:
I have a derived type, e.g.

type circle_datatype
real :: radius
real :: x
real :: y
real :: z
character(len=*) :: circle_label
endtype circle_datatype
type(circle_datatype) :: circle


and want to refer to the individual elements via some indexing scheme, say in this example I want to change the value of circle%radius I would use index #1, or the z-coordinate I would use #4. Is there some method by which this is possible?

I think IDL has a system for this, such that circle.radius can be referenced by circle.(0), but I really need Fortran's horsepower for this code!

If you don't mind making the code clumsy, error-prone, and difficult
to read, it's trivial ;).

Create a hidden helper type, something like
type helper
integer :: index
real :: x
character(len=whatever) :: c
! any other types that are in circle_datatype
endtype helper

Next create some generic operators or functions that return type
helper results.
i .func. value
or maybe
func(i,value)
returns a type helper result with the index set to i, and the
appropriate x or c set to value. You'll, obviously, need one
function for each type of element in circle_datatype. The
character one is trivial, the real one needs a select case.

You can then also provide overloads to do arithmetic between
type helper and the intrinsic types, helper types, and
circle_datatype and return type helper.

(i .func. circle) * 3.14 * (j .func. other_circle)**2

Then create an assignment operator that assigns type helper to
type circle by using an internal select case to assign to the
INDEXth element.

The result is that
circle = i .func. value

is ultimately equivalent to
call assigner(circle, i, value)

I'm not real happy with putting the circle subscript on the right,
it's ugly and error-prone. But I think it'll work.

After thinking about this, why not just create a few generic
subroutines that implement the above call if you only want to
do assignments that update (but not use) elements?

If you're not in a big hurry and can wait until 2008, the new
Fortran allows pointer functions on the left hand side.
You could probably make
circle.element.i = whatever
do what you want. But that won't be standard until later this
year. It might take even longer to get a F2008 compiler :(.

*** Hendrickson
.