Could anyone show me how to create a derived type with a type-bound procedure inside a function/subroutine? Since I am not sure if I can create a module inside a function/subroutine, I am not sure how to get this done.
It’s unclear what you mean by, “how to create a derived type with a type-bound procedure inside a function/subroutine.”
Re: “… create a module inside a function/subroutine …,” perhaps you will find the following pictorial from the Fortran standard useful:
In the above, you will note there is no option to “create a module inside a function/subroutine.” However you can create a module subprogram and “CONTAIN” it in a module.
Now a similar concept applies to definitions such as those toward a derived type. You can have a derived type definition in a program unit like those in the first box in the picture above. Then you can bind a function/subroutine that is a module subprogram to such a type but not an internal program which effectively means a type definition with a type-bound procedure has to be in a module. (The standard, by the way, does allow a type-bound procedure to be an external procedure as long as it has explicit interface but I don’t recommend external procedures in this day and age hence I add this in brackets as an afterthought that is best ignored)
So, re: “how to create a derived type with a type-bound procedure inside a function/subroutine?”, you will know the following conforms:
! An external procedure with a type definition
subroutine sub()
type :: t
integer :: n = 0
end type
type(t) :: foo
call foo%n = 42
print *, "foo%n = ", foo%n
end subroutine
But now if you want to add a type-bound procedure and say for starters it is one where the PASS
attribute is present meaning the polymorphic instance (object) of the type in question is one of the required dummy arguments of the procedure, then should you attempt the following, a conforming processor is one that recognizes it is a violation of the standard:
! An external procedure
subroutine sub()
type :: t
integer :: n
contains
procedure :: set => set_t !<-- not allowed since set_t is an internal subprogram
end type
type(t) :: foo
call foo%set( n=42 )
print *, "foo%n = ", foo%n
contains
subroutine set_t( this, n )
class(t), intent(inout) :: this
integer, intent(in) :: n
this%n = n
end subroutine
end subroutine
But now, as many examples on this site over its ~2 years of age have shown the readers here, you can have the derived type definition in a module that CONTAINs the type-bound procedure as a module subprogram and your function/subroutine can simply USE it.
I understand that module part. I need to call Fortran subroutines from R, which does not work well with Fortran modules. That’s why I asked this question.
In C++, class member functions can be defined inside a class, which does not have this issue. I am not sure why Fortran does not allow defining functions/subroutines inside a derived type.
The ecosystem around R appears to know nothing beyond some old legacy dialect of FORTRAN from around the time way back when S went from alpha to beta.
And that same ecosystem works far better with C than other compiler-based languages.
Then given C interoperability in Fortran, it might prove much more convenient to employ that in conjunction with many other modern features of Fortran starting with modules from Fortran 90, albeit with some added verbosity that comes with the Fortran territory.
Can you provide a minimal working example of the case at hand with R where you seek to use a derived type in Fortran with a type-bound procedure? Readers may be able to point out how to retain the use of modules in Fortran whilst consuming the solution in R.
Thanks for the advice. I am just exploring the Fortran OOP features and find that, unlike C++, Fortran seems to not allow defining type-bound procedures inside a type. A module is needed to do that. It doesn’t matter until I need to call my Fortran codes from R. Not sure why it is designed like this.
Found someone who asked a very simillar question:
https://mailman.j3-fortran.org/pipermail/j3/2021-December/013483.html
MODULE
s are foundational to the practice of modern Fortran. While there can be pedagogical and/or some special-case arguments toward support for aspects extraneous to the use of MODULE
s in Fortran such as with external procedures and particular support toward them with the object-oriented approach, considering the highly resource-constrained environment with Fortran, those arguments will likely be much, much, much lower on the priority list for the standard-bearers for Fortran. While the question as to why things were designed as they were may carry some academic interest, it is mostly immaterial practically.
As things stand, any meaningful use of object-oriented features in Fortran require MODULE
s, just as anything remotely practicable with C++ beyond toy projects or single or a few user solutions call for a judicious application of namespace
management in C++. Currently MODULE
s in Fortran provide some such service around namespace
s and that is another consideration for MODULE
s.
That R “does not work well with Fortran modules” is a separate issue that is better addressed on the R side.
Just out of curiosity, is it not possible to compile multiple Fortran sources for use in R?
(or possibly, make an .so file by compiling the library codes first and then using that .so
file from R?)
I think it is indeed “possible to compile multiple Fortran sources for use in R.” But the problem is often the solution design with Fortran can follow a certain pattern which a) is somewhat different from other language (C++, C) solutions and b) the one with Fortran may not catch everyone’s fancy since it may require specific attention to details to get mostly around R’s effective ignorance of developments in Fortran since the 1970s.
But now, admittedly my experience is limited to Windows OS and one case several years ago where a Fortran DLL (equivalent to .so on *ux) library solution involving many derived types and type-bound procedures built with Intel Fortran were consumed by a team I worked with via a binary extension in R where the extension itself was mainly a thin C wrapper layer built using whichever GCC toolchain that came with R.
Have you looked at what the BayesFM package does? It uses modules and type-bound procedures, and it has met the requirements to be listed on CRAN.
Very interesting!