Type-bound procedures inside a function/subroutine

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.

@fortran4r,

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)

2 Likes

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.

2 Likes

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

1 Like

MODULEs 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 MODULEs 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 MODULEs, 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 MODULEs in Fortran provide some such service around namespaces and that is another consideration for MODULEs.

That R “does not work well with Fortran modules” is a separate issue that is better addressed on the R side.

2 Likes

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.

2 Likes

Very interesting!