I was wondering if one could do the following task without writing the subroutine for every possible input type and then defining and interface.
I want to write a subroutine which takes a message of type character and one variable of a type like: integer, double, float, complex, logical, character, own type(matrix). The subroutine then should just simply print the message and after that print the variable. However I want to use an own print subroutine for my own types. In Java I could override the .toString() - method which is inherited from the general Object class to every other class. Is there a similar way to affect the way how my own type is printed when calling something like print*, VariableOfOwnType?
And how do I declare such a general argument in Fortran? In Java I could simply say that the argument is of type object. Please share your wisdom :)
Related
I recently started to dive into OOP with Fortran. I have a type hierarchy where I have an abstract base type genericProblem and a derived type specificProblem. specificProblem has a subroutine that is not defined in genericProblem, called "InitializeWith" in my example.
It seems that I misunderstood the select type construct. I thought it was made specifically for such cases where I know I can expect the variable problem to be of a certain (derived) type of genericProblem and that the compiler should know that "I'm apparently of type specificProblem now function calls specific to that type are ok".
I am however getting a
This is not a field name that is defined in the encompassing structure.
error with the example below, so I am probably missing out something. Could someone point me in the right direction?
subroutine AssignSomething(problem,rhsTarget)
class(genericProblemT), intent(in out) :: problem
class(genericProblemT), target, intent(in) :: rhsTarget
select type (lhsProblem => problem)
type is (specificProblemT)
! Try setting up the rhsProblem:
call lhsProblem%InitializeWith(rhsTarget) ! Gives an error
class default
! give error for unexpected/unsupported type
throw some error
end select
end subroutine AssignSomething
I am trying to use pointers to create links between objects. Using Fortran and here is the code piece:
module base_pars_module
type,abstract,public :: base_pars
end type
end module
module test_parameters_module
use base_pars_module
type, extends(base_pars) :: test_pars
contains
procedure :: whoami
end type
contains
function whoami(this) result(iostat)
class( test_pars) :: this
write(*,*) 'i am a derived type child of base_pars'
end type
end module
module base_mask_module
use base_pars module
type, abstract , public :: base_mask
class(base_pars),pointer :: parameters
end type
end module
module test_mask_module
use base_mask_module
implicit none
type, extends(base_mask) :: test_mask
end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
iostat= par_test%whoami()
mask_test%parameters=>par_test
iostat=mask_test%parameters%whoami()
end program
parameters at base_mask_module is a pointer with base_pars class. I would like to use this pointer to refer par_test object which is test_pars type that extends base_pars type. So the pointer and the target has the same class. But when I compile this it gives an error:
driver.f90:17.37:
iostat=mask_test%parameters%whoami()
1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure
Is it a bug or am i doing something wrong?
When you have polymorphism like this there are two things to consider about an object: its dynamic type and its declared type. The parameters component of test_mask (base_mask) is declared as
class(base_pars),pointer :: parameters
Such a component therefore has declared type base_pars.
Come the pointer assignment
mask_test%parameters=>par_test
mask_test%parameters has dynamic type the same as par_test: test_pars. It's of declared type base_pars, though, and it's the declared type that is important when we care about its components and bindings. base_pars indeed has no whoami.
You need, then, something which has declared type par_test. Without changing the definitions of the derived types you can do this with the select type construct.
select type (pars => mask_test%parameters)
class is (par_test)
iostat=pars%whoami() ! pars of declared type par_test associated with mask_test%parameters
end select
That said, things get pretty tedious quite quickly with this approach. Always using select type, distinguishing between numerous extending types, will be quite a bind. An alternative would be to ensure that the declared type base_pars has a binding whoami. Instead of changing the main program as above, we alter the module base_pars_module:
module base_par_modules
implicit none ! Encourage good practice
type,abstract,public :: base_pars
contains
procedure(whoami_if), deferred :: whoami
end type
interface
integer function whoami_if(this)
import base_pars ! Recall we're in a different scope from the module
class(base_pars) this
end function
end interface
end module
So, we've a deferred binding in base_pars that is later over-ridden by a binding in the extending type test_pars. mask_test%parameters%whoami() in the main program is then a valid and the function called is that offered by the dynamic type of parameters.
Both approaches here address the problem with the binding of the declared type of parameters. Which best suits your real-world problem depends on your overall design.
If you know that your hierarchy of types will all have enough in common with the base type (that is, all will offer a whoami binding) then it makes sense to go for this second approach. Use the first approach rather when you have odd special cases, which I'd suggest should be rare.
I am trying to design a data structure composed of objects which contain, as instance variables, objects of another type.
I'd like to be able to do something like this:
CALL type1_object%get_nested_type2_object()%some_type2_method()
Notice I am trying to immediately use the getter, get_nested_type2_object() and then act on its return value to call a method in the returned type2 object.
As it stands, gfortran v4.8.2 does not accept this syntax and thinks get_nested_type2_object() is an array reference, not a function call. Is there any syntax that I can use to clarify this or does the standard not allow this?
To give a more concrete example, here is some code illustrating this:
furniture_class.F95:
MODULE furniture_class
IMPLICIT NONE
TYPE furniture_object
INTEGER :: length
INTEGER :: width
INTEGER :: height
CONTAINS
PROCEDURE :: get_length
END TYPE furniture_object
CONTAINS
FUNCTION get_length(self)
IMPLICIT NONE
CLASS(furniture_object) :: self
INTEGER :: get_length
get_length = self%length
END FUNCTION
END MODULE furniture_class
Now a room object may contain one or more furniture objects.
room_class.F95:
MODULE room_class
USE furniture_class
IMPLICIT NONE
TYPE :: room_object
CLASS(furniture_object), POINTER :: furniture
CONTAINS
PROCEDURE :: get_furniture
END TYPE room_object
CONTAINS
FUNCTION get_furniture(self)
USE furniture_class
IMPLICIT NONE
CLASS(room_object) :: self
CLASS(furniture_object), POINTER :: get_furniture
get_furniture => self%furniture
END FUNCTION get_furniture
END MODULE room_class
Finally, here is a program where I attempt to access the furniture object inside the room (but the compiler won't let me):
room_test.F95
PROGRAM room_test
USE room_class
USE furniture_class
IMPLICIT NONE
CLASS(room_object), POINTER :: room_pointer
CLASS(furniture_object), POINTER :: furniture_pointer
ALLOCATE(room_pointer)
ALLOCATE(furniture_pointer)
room_pointer%furniture => furniture_pointer
furniture_pointer%length = 10
! WRITE(*,*) 'The length of furniture in the room is', room_pointer%furniture%get_length() - This works.
WRITE(*,*) 'The length of furniture in the room is', room_pointer%get_furniture()%get_length() ! This line fails to compile
END PROGRAM room_test
I can of course directly access the furniture object if I don't use a getter to return the nested object, but this ruins the encapsulation and can become problematic in production code that is much more complex than what I show here.
Is what I am trying to do not supported by the Fortran standard or do I just need a more compliant compiler?
What you want to do is not supported by the syntax of the standard language.
(Variations on the general syntax (not necessarily this specific case) that might apply for "dereferencing" a function result could be ambiguous - consider things like substrings, whole array references, array sections, etc.)
Typically you [pointer] assign the result of the first function call to a [pointer] variable of the appropriate type, and then apply the binding for the second function to that variable.
Alternatively, if you want to apply an operation to a primary in an expression (such as a function reference) to give another value, then you could use an operator.
Some, perhaps rather subjective, comments:
Your room object doesn't really contain a furniture object - it holds a reference to a furniture object. Perhaps you use that reference in a manner that implies the parent object "containing" it, but that's not what the component definition naturally suggests.
(Use of a pointer component suggests that you want the room to point at (i.e. reference) some furniture. In terms of the language, the object referenced by a pointer component is not usually considered part of the value of the parent object of the component - consider how intrinsic assignment works, restrictions around modifying INTENT(IN) arguments, etc.
A non-pointer component suggests to me that the furniture is part of the room. In a Fortran language sense an object that is a non-pointer component it is always part of the value of the parent object of the component.
To highlight - pointer components in different rooms could potentially point at the same piece of furniture; a non-pointer furniture object is only ever directly part of one room.)
You need to be very careful using functions with pointer results. In the general case, is it:
p = some_ptr_function(args)
(and perhaps I accidentally leak memory) or
p => some_ptr_function(args)
Only one little character difference, both valid syntax, quite different semantics. If the second case is what is intended, then why not just pass the pointer back via a subroutine argument? An inconsequential difference in typing and it is much safer.
A general reminder applicable to some of the above - in the context of an expression, evaluation of a function reference yields a value. Values are not variables and hence you are not permitted to vary [modify] them.
I'm writing some code in Fortran 2003 that does a lot of linear algebra with sparse matrices. I'm trying to exploit some of the more abstract features of the new standard so I have simpler programs without too much repeated code.
I have a procedure solver which takes in a matrix, some vectors, the tolerance for the iterative method used etc. I'm passing a pointer to a procedure called matvec to it; matvec is the subroutine we use for matrix-vector multiplications.
The problem is, sometimes matvec is a procedure which takes in extra arguments colorlist, color1, color2 above the usual ones sent to this procedure. I can think of several ways of dealing with this.
First idea: define two different abstract interfaces matvec1, matvec2 and two different solvers. This works but it means duplicating some code, which is just what I'm trying to avoid.
Another idea: keep the same abstract interface matvec, and make the extra arguments colorlist, color1, color2 optional. That means making them optional in every matvec routine -- even ones for which they're not really optional, and for routines where they're not even used at all. Pretty sure I'll go to hell if I do this.
I can think of plenty of other less than optimal solutions. I'd like some input on this -- I'm sure there's some elegant way to do it, I'm just not sure what it is.
The question is really, whether the additional arguments must be passed every time the procedure is invoked (because they change between two invocations), or they can be initialized at some point and then just used in the function. In the later case you could create a class with an abstract interface, which defines your subroutine matvec with the essential arguments. You can then extend that class with more specialized ones, which can hold the additional options needed. They will still have to define the same matvec interface as the parent class (with the same argument list), but they can use the additional values stored in them when their matvec procedure is called.
You find a detailed example in this answer for a similar case (look for the second example showing module rechercheRacine).
Instead of passing the procedure pointer as an explicit argument, you could put the various matvec routines behind a generic interface:
interface matvec
module procedure matvec1, matvec2
end interface
Then your solver routine can just use the generic name with or without the extra arguments. The same approach can of course also be taken when using Bálint's suggested approach of defining a solver as a derived type with type-bound procedures:
type :: solver
real, allocatable :: matrix(:,:), v1(:), v2(:)
contains
procedure, pass :: matvec1
procedure, pass :: matvec2
generic :: matvec => matvec1, matvec2
end type
The main difference is that this does not use polymorphism to determine the correct procedure to invoke, but rather the characteristics of the dummy arguments.
I'm not sure of your intentions for the procedure pointer; if you wish to change its target at runtime (or perhaps assign some special meaning to its 'undefined' status), then pointers are the only way and all targets need to match the same abstract interface. If instead you just need to select one of several procedures based on their arguments, then you can exploit interfacing (my example) or overloading (Bálint's example). Each extension of a type can extend an inherited generic binding with new procedures, or overload an inherited specific binding.
In Fortran, is there a way to determine the type of a variable?
A possible use case where the type of a variable would be needed is the following. We pass a variable's type as an argument to a function, to be able to call type-specific code with that function, thus eliminating the need to have separate similar functions for each data type.
Well you might be able to do what you want if you mess about with the KIND intrinsic and POINTERs, but if you are only concerned with the signature of functions and subroutines, leave it to Fortran. If you define
function calc8(arg1)
real(8), intent(in) :: arg1
...
and
function calc4(arg1)
real(4), intent(in) :: arg1
...
in a module, and declare an interface like this
interface calc
module procedure calc8
module procedure calc4
end interface
(Warning, I haven't checked the syntax in detail, that's your responsibility.)
then Fortran will match the call to the right version of the function. Sure, you have to write both versions of the function, but that's really the Fortran 95 way of doing it. This can be quite tedious, I tend to write a generic version and run a sed script to specialise it. It's a bit of a kludge but it works.
If the code of the function is identical apart from the kind of the arguments I sometimes write the function for real(8) (or whatever) and write a version for real(4) which calls the real(8) version wrapped in type conversions.
In Fortran 2003 there are improved ways of defining polymorphic and generic functions, but I haven't really got my head around them yet.
Yes, there are two ways.
The first way does requires you to write separate functions or subroutines for each variable type, but you don't have to call different functions. This may or may not be close enough to what you want. You write the separate routines, then to write an interface to create a generic function or subroutine wrapping these specific subroutines. You don't have to pass the variable type, or do anything special in your call -- it is all done via the declaration and automatically by the compiler from the variable itself, as long as the variables are different enough that the compiler can distinguish them (there are rules about what is required). This is similar to how intrinsic functions work -- you can call sin with a real argument, a double precision real argument or a complex argument and the compiler calls the correct actual function and returns the matching result. High Performance Mark sketched a solution along these lines. For another question, I posted a working example, where the distinguishing feature of the variables was array rank: how to write wrapper for 'allocate'. An advantage of this method is that it is widely support by Fortran compilers.
In Fortran 2003/2008 there are extensive object oriented features. Quoting "Fortran 95/2003 explained" by Metcalf, Reid and Cohen, "To execute alternative code depending on the dynamic type of a polymorphic entity and to gain access to the dynamic parts, the select type construct is provided." The select type statement is a bit similar to a select case statement. This is support by fewer compilers. Again, you don't have to pass the type, since the compiler can figure it you from the variable itself. But it has to be a polymorphic type... Both Intel ifort and gfortran list select type and polymorphic datatypes as supported -- the later with some experimental aspects in gfortran (http://gcc.gnu.org/wiki/Fortran2003). These are recent additions to these compilers.
Here is a piece of code that determines what the type of something is. The action is trivial but you should be able to extend it to your use case.
module element_to_datatype
use iso_fortran_env
use mpi_f08
implicit none
contains
function get_element_datatype(element) result(datatype)
class(*), intent(in) :: element
type(MPI_Datatype) :: datatype
select type(element)
! REAL types
type is ( real(kind=REAL32) )
datatype = MPI_REAL4
type is ( real(kind=REAL64) )
datatype = MPI_REAL8
! COMPLEX types
type is ( complex(kind=REAL32) )
datatype = MPI_COMPLEX8
type is ( complex(kind=REAL64) )
datatype = MPI_COMPLEX16
! INTEGER types
type is ( integer(kind=INT8) )
datatype = MPI_INTEGER1
type is ( integer(kind=INT16) )
datatype = MPI_INTEGER2
type is ( integer(kind=INT32) )
datatype = MPI_INTEGER4
type is ( integer(kind=INT64) )
datatype = MPI_INTEGER8
! OTHER types
type is ( logical )
datatype = MPI_LOGICAL
end select
end function
end module element_to_datatype
A previous answer shows how to do this with interfaces, so I won't repeat that.