From: Bam Ting on
Hi
f90 the compiler does seem to distinguish between methods from user
defined types. I have two type one "has a" instance of the other. Both
have a methods named Print (with different typed arguments). I want
both user defined type to have the same method Print and be callable
by each other. How can I do what I want?

module BoxModule
type Box
....
end type
contains
subroutine Print(b)
type(Box) b
....
end subroutine
end module

module OtherModule
type Other
....
type(Box) b
....
end type
contains
subroutine Print(o) ! <----------------------------- compiler doesn't
like this
type(Other) o
....
Print(o%b)
....
end subroutine
end module


subroutine Print(c)
1
use BoxModule
2
Error: Procedure 'print' at (1) is already defined at (2)

From: Richard Maine on
Bam Ting <bampingting(a)gmail.com> wrote:

> f90 the compiler does seem to distinguish between methods from user
> defined types. I have two type one "has a" instance of the other. Both
> have a methods named Print (with different typed arguments). I want
> both user defined type to have the same method Print and be callable
> by each other. How can I do what I want?

Your terminology makes the question confusing. Fortran doesn't have
"methods". It does have procedures. While procedures can bear some
relationship with what are sometimes called methods, they aren't
identical and you'll likely cause great confusion, both to yourself and
others, if you refer to procedures as methods. The type-bound procedures
introduced in f2003 are more like "methods", but that's not an f90
feature.

And talking about "methods from user defined types" just makes the
confusion worse. You can't define a procedure in a type - not in f90.
You can, as your code does, define a type and a procedure that operates
on that type in the same module. But the procedure is not in any sense
"from" the type. It is from the module and happens to have an argument
of the type.

> module BoxModule
> type Box
> ...
> end type
> contains
> subroutine Print(b)
> type(Box) b
> ...
> end subroutine
> end module
>
> module OtherModule
> type Other
> ...
> type(Box) b
> ...
> end type
> contains
> subroutine Print(o) ! <----------------------------- compiler doesn't
> like this
> type(Other) o
> ...
> Print(o%b)
> ...
> end subroutine
> end module


The closest thing in f90 to what I think you are asking for is a generic
procedure. You give the specific procedures all different names (perhaps
something like print_box and print_other), but then put them all in a
generic named print. Multiple specific procedures can share the same
generic name - that's what generics are about. You cannot, however, have
two specific procedures of the same name in the same scope. The compiler
wouldn't know which one you are talking about; if you expect it to tell
based on the argument types, well, that's what generic procedures do.

That would address the problem you illustrate above, but your
description hints at another problem when you talk about having them
call "each other". Module USE statements cannot be recursive. That is,
if module OTHER used module BOX, then module BOX cannot also use module
OTHER. Your code doesn't illustrate that problem, but your description
alludes to it. If indeed you do need them to be able to call each other,
that can be tricky in f90. The solutions tend to be a bit awkward and
involve some restructuring.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: Bam Ting on
On Mar 17, 8:40 pm, nos...(a)see.signature (Richard Maine) wrote:
> Bam Ting <bampingt...(a)gmail.com> wrote:
> > f90 the compiler does seem to distinguish between methods from user
> > defined types. I have two type one "has a" instance of the other. Both
> > have a methods named Print (with different typed arguments). I want
> > both user defined type to have the same method Print and be callable
> > by each other. How can I do what I want?
>
> Your terminology makes the question confusing. Fortran doesn't have
> "methods". It does have procedures. While procedures can bear some
> relationship with what are sometimes called methods, they aren't
> identical and you'll likely cause great confusion, both to yourself and
> others, if you refer to procedures as methods. The type-bound procedures
> introduced in f2003 are more like "methods", but that's not an f90
> feature.
>
> And talking about "methods from user defined types" just makes the
> confusion worse. You can't define a procedure in a type - not in f90.
> You can, as your code does, define a type and a procedure that operates
> on that type in the same module. But the procedure is not in any sense
> "from" the type. It is from the module and happens to have an argument
> of the type.
>
>
>
> > module BoxModule
> > type Box
> > ...
> > end type
> > contains
> > subroutine Print(b)
> > type(Box) b
> > ...
> > end subroutine
> > end module
>
> > module OtherModule
> > type Other
> > ...
> > type(Box) b
> > ...
> > end type
> > contains
> > subroutine Print(o) ! <----------------------------- compiler doesn't
> > like this
> > type(Other) o
> > ...
> > Print(o%b)
> > ...
> > end subroutine
> > end module
>
> The closest thing in f90 to what I think you are asking for is a generic
> procedure. You give the specific procedures all different names (perhaps
> something like print_box and print_other), but then put them all in a
> generic named print. Multiple specific procedures can share the same
> generic name - that's what generics are about. You cannot, however, have
> two specific procedures of the same name in the same scope. The compiler
> wouldn't know which one you are talking about; if you expect it to tell
> based on the argument types, well, that's what generic procedures do.
>
> That would address the problem you illustrate above, but your
> description hints at another problem when you talk about having them
> call "each other". Module USE statements cannot be recursive. That is,
> if module OTHER used module BOX, then module BOX cannot also use module
> OTHER. Your code doesn't illustrate that problem, but your description
> alludes to it. If indeed you do need them to be able to call each other,
> that can be tricky in f90. The solutions tend to be a bit awkward and
> involve some restructuring.
>
> --
> Richard Maine                    | Good judgment comes from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle           |  -- Mark Twain

Thanks for the reply!

It's not recursive sorry for the confusing language. I have one type
that has as its members instances of another type. I want a
specialized subroutine Print associated with both types that knows how
to print all of its members. In the type that contains I need to call
Print on the contained instances during Print. I hope that's clearer.
I'm not very good with fortran so I don't know all of the terminology.
I thought the compiler should be able to differentiate between
functions with different typed arguments.

I guess I'm after a generic procedure. But I had hoped to keep the
user defined types implementations separate and self contained where
possible, eg. Box doesn't need to know anything about Other.

Thanks again
From: jwm on
On Mar 18, 12:02 am, Bam Ting <bampingt...(a)gmail.com> wrote:

> I guess I'm after a generic procedure. But I had hoped to keep the
> user defined types implementations separate and self contained where
> possible, eg. Box doesn't need to know anything about Other.

What about this:



module BoxModule

implicit none
private

type, public :: Box
....
end type

interface Print
module procedure Print
end interface
public Print

contains
subroutine Print(b)
type(Box), intent(IN) :: b
....
end subroutine
end module

module OtherModule

implicit none
use BoxModule
private

type, public :: Other
....
type(Box) :: b
....
end type

interface Print
module procedure PrintOther
end interface
public Print

contains
subroutine PrintOther(o)

type(Other), intent(IN) :: o
....
call Print(o%b)
....
end subroutine
end module

program main

use OtherModule
use BoxModule
implicit none

type(Box) :: a
type(Other) :: b
....
call Print(a)
call Print(b)
....
end program
From: Richard Maine on
Bam Ting <bampingting(a)gmail.com> wrote:

> I guess I'm after a generic procedure. But I had hoped to keep the
> user defined types implementations separate and self contained where
> possible, eg. Box doesn't need to know anything about Other.

They don't have to know about each other to make a generic. Each
separately gives the generic name to its own specific.


--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain