- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a collection of routines in submodules, many of which have an identical interface specification. The ancestor module (see attached) defines all these interfaces separately. I would like to use an ABSTRACT INTERFACE to reduce the verbosity and duplication in this module. However, I can't get the syntax right, nothing I try will compile. Anyone know how to do it?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm dealing with the same problem in my codes.
Here what I'm doing:
module net_func_branches_interfaces_mod use dummy_types implicit none interface # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, outlet_fprop, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(in ) :: spres ; \ real(8) , intent(inout) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_flash_results) , intent(out ) :: outlet_fprop ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_binjector) _ProcedureInterface_(net_func_branches_bseparator) _ProcedureInterface_(net_func_branches_compressor) # undef _ProcedureInterface_ # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(in ) :: spres ; \ real(8) , intent(in ) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_fcv) _ProcedureInterface_(net_func_branches_nrv) _ProcedureInterface_(net_func_branches_pcv) # undef _ProcedureInterface_ # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, fpropo, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(inout) :: spres ; \ real(8) , intent(inout) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_flash_results) , intent(out ) :: fpropo ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_choke) _ProcedureInterface_(net_func_branches_connector) # undef _ProcedureInterface_ end interface end module
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could use an include file with the common arguments declared
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I guess it depends how you want to use them. You can have an abstract interface and then define procudure pointers (of that type) to the actual implimentation routine names which then become normal rather than module subroutines in the submodule
I hate include files BTW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I wanted to do something similar recently, and concluded that the language does not allow for this. Ideally one would want to use PROCEDURE(abstract-name) to declare the non-abstract interface, but one can't. At least for submodules you don't have to repeat the argument list in the submodule itself using MODULE PROCEDURE (but you can if you want to.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Colin W.,
To the best of my understanding, ABSTRACT INTERFACE facility in the Fortran standard does not provide any solution to what you are looking for in "reduce the verbosity and duplication.", particularly in the context of SUBMODULEs.
See this site: https://github.com/j3-fortran/fortran_proposals.
I suggest you make a proposal there with details of the facility you seek - I think it will be a useful addition to the language to include better interface facility which can reduce verbosity and duplication that then helps develop less error-prone and more expressive code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm dealing with the same problem in my codes.
Here what I'm doing:
module net_func_branches_interfaces_mod use dummy_types implicit none interface # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, outlet_fprop, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(in ) :: spres ; \ real(8) , intent(inout) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_flash_results) , intent(out ) :: outlet_fprop ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_binjector) _ProcedureInterface_(net_func_branches_bseparator) _ProcedureInterface_(net_func_branches_compressor) # undef _ProcedureInterface_ # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(in ) :: spres ; \ real(8) , intent(in ) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_fcv) _ProcedureInterface_(net_func_branches_nrv) _ProcedureInterface_(net_func_branches_pcv) # undef _ProcedureInterface_ # define _ProcedureInterface_(ProcedureName) \ module subroutine ProcedureName(net, ib, irow, spres, epres, rate, func, derv, fpropo, ehs); \ type(t_network), target, intent(inout) :: net ; \ integer , intent(in ) :: ib ; \ integer , intent(in ) :: irow ; \ real(8) , intent(inout) :: spres ; \ real(8) , intent(inout) :: epres ; \ real(8) , intent(in ) :: rate ; \ logical , intent(in ) :: func ; \ logical , intent(in ) :: derv ; \ type(t_flash_results) , intent(out ) :: fpropo ; \ type(t_ehs) , intent(inout) :: ehs ; \ end subroutine _ProcedureInterface_(net_func_branches_choke) _ProcedureInterface_(net_func_branches_connector) # undef _ProcedureInterface_ end interface end module
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The ability to use an abstract (generic) interface to apply a a family of submodule routines would be very helpful language feature. A common use case I see is Win API callbacks that must all have the same (pre-defined) interface.
I suggested in #3 that you could do this with procedure pointers so I had a play to see what could be done. I managed to get something to work but maybe it is not a good way???? Discuss!
module net_branches_interfaces_mod implicit none abstract interface subroutine net_branches(net, ib) integer , intent(in ) :: net integer , intent(out ) :: ib end subroutine net_branches end interface interface module subroutine init_net_branches_interfaces_mod() end subroutine init_net_branches_interfaces_mod end interface ! use ABSTRACT INTERFACE procedure(net_branches), pointer :: net_branches_binjector => null() procedure(net_branches), pointer :: net_branches_block => null() procedure(net_branches), pointer :: net_branches_bseparator => null() end module net_branches_interfaces_mod submodule(net_branches_interfaces_mod) net_branches_interfaces_mod_subs implicit none contains module subroutine init_net_branches_interfaces_mod() net_branches_binjector => m_net_branches_binjector net_branches_block => m_net_branches_block net_branches_bseparator => m_net_branches_bseparator end subroutine init_net_branches_interfaces_mod subroutine m_net_branches_binjector(net, ib) integer , intent(in ) :: net integer , intent(out ) :: ib ib = net + 1 end subroutine subroutine m_net_branches_block(net, ib) integer , intent(in ) :: net integer , intent(out ) :: ib ib = net + 2 end subroutine subroutine m_net_branches_bseparator(net, ib) integer , intent(in ) :: net integer , intent(out ) :: ib ib = net + 3 end subroutine end submodule net_branches_interfaces_mod_subs program test use net_branches_interfaces_mod implicit none integer :: i, j call init_net_branches_interfaces_mod() i = 1 call net_branches_binjector(i,j) print *, j end program test
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
andrew_4619 wrote:.. I suggested in #3 that you could do this with procedure pointers so I had a play to see what could be done. I managed to get something to work but maybe it is not a good way???? Discuss! ..
What you show with procedure pointers is a workaround that some might find interesting. They can consider it while the Fortran language takes at least 20 years or so to offer a solution for this i.e., if at all they take this up for feature development in a future standard revision. Meaning the earliest it can even be considered is Fortran 202Y which may come due circa 2028 and another 10 years for half-decent compiler implementations that coders can have confidence to use.
With all the teams I've worked with, this is mostly moot now because they have all moved away from modern Fortran at a very rapid clip over the last 2-3 years. But when Fortran was on the table, the 2 big considerations were with code structures and build tool-chains:
- Avoid large files and encapsulate important business/technical computing instructions in separate file units to get added control as to who has access to what,
- Minimize build dependencies, especially with libraries and avoid compilation cascades
SUBMODULEs provided promise to help with both of above considerations.
However if subprograms such as "m_net_branches_binjector", "m_net_branches_block", etc. are simply CONTAINed procedures in the SUBMODULE net_branches_interfaces_mod_subs, then that would have been a no-no, particularly if these procedures were large subprograms and/or they captured important and sensitive compute instructions.
But if these procedures are not big nor sensitive, then why bother with a SUBMODULE at all? One can simply CONTAIN them in the parent MODULE (net_branches_interfaces_mod) itself.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
However if subprograms such as "m_net_branches_binjector", "m_net_branches_block", etc. are simply CONTAINed procedures in the SUBMODULE net_branches_interfaces_mod_subs, then that would have been a no-no, particularly if these procedures were large subprograms and/or they captured important and sensitive compute instructions.
The example code makes use of submodules so you can play with the routines without any build cascade which is important to me. I don't quite understand your point above, the routines in the submodule are exposed to the world via the abstract interface and the procedure pointer, but other than that (to me anyway) have the same 'status' to the world as if they were module procedures exposed by that mechanism. I don't think i would in general use this construct I think would cut/paste/edit the interface N times (as I do from time to time already). Maybe you could elaborate a little so I can understand the thinking better.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan
I have taken your advice and opened a new proposal, see:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Colin W. wrote:FortranFan
I have taken your advice and opened a new proposal, see:
Awesome, thank you!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What language are these programmers moving to if not Fortran?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Nichols, John wrote:What language are these programmers moving to if not Fortran?
@John Nichols, you're in academia: you must be aware of the languages taught by schools and universities broadly as well as in science and engineering departments globally. Note that list is not all that different from the top 9 on IEEE survey:
https://spectrum.ieee.org/computing/software/the-top-programming-languages-2019
And these are the languages being used in industry as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear FortranFan:
Unluckily I am in a construction department - I married an American women and needed a job.
I see some code development, but a lot of what I see is Python and Matlab. I hate MATLAB as a teaching tool, the student's I have seen do not understand how to program and the programs cannot solve large problems. This is not true across the spectrum -- but I do not see the CompSci people.
Our computer support people rave about Python. Python is embedded in Rhino. I tried it to develop a FEM modeller - after 10,000 lines and by my estimate at least 20000 to go I gave up - it is not a nice language. It is also slow.
I was forced into C# by the manufacturer of the accelerometer, the driver interface is written in C#. So I spend a lot of time in that language, the real pity is put a few of the features in Fortran and you have a perfect language.
Thank you for the IEEE reference.
And also this forum is the best.
John
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page