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.
Related
I'm very new to Fortran, and for my research I need to get a monster of a model running, so I am learning as I am going along. So I'm sorry if I ask a "stupid" question.
I'm trying to compile (Mac OSX, from the command line) and I've already managed to solve a few things, but now I've come across something I am not sure how to fix. I think I get the idea behind the error, but again, not sure how to fix.
The model is huge, so I will only post the code sections that I think are relevant (though I could be wrong). I have a file with several subroutines, that starts with:
!==========================================================================================!
! This subroutine simply updates the budget variables. !
!------------------------------------------------------------------------------------------!
subroutine update_budget(csite,lsl,ipaa,ipaz)
use ed_state_vars, only : sitetype ! ! structure
implicit none
!----- Arguments -----------------------------------------------------------------------!
type(sitetype) , target :: csite
integer , intent(in) :: lsl
integer , intent(in) :: ipaa
integer , intent(in) :: ipaz
!----- Local variables. ----------------------------------------------------------------!
integer :: ipa
!----- External functions. -------------------------------------------------------------!
real , external :: compute_water_storage
real , external :: compute_energy_storage
real , external :: compute_co2_storage
!---------------------------------------------------------------------------------------!
do ipa=ipaa,ipaz
!------------------------------------------------------------------------------------!
! Computing the storage terms for CO2, energy, and water budgets. !
!------------------------------------------------------------------------------------!
csite%co2budget_initialstorage(ipa) = compute_co2_storage(csite,ipa)
csite%wbudget_initialstorage(ipa) = compute_water_storage(csite,lsl,ipa)
csite%ebudget_initialstorage(ipa) = compute_energy_storage(csite,lsl,ipa)
end do
return
end subroutine update_budget
!==========================================================================================!
!==========================================================================================!
I get error messages along the lines of
budget_utils.f90:20.54:
real , external :: compute_co2_storage
1
Error: Dummy argument 'csite' of procedure 'compute_co2_storage' at (1) has an attribute that requires an explicit interface for this procedure
(I get a bunch of them, but they are essentially all the same). Now, looking at ed_state_vars.f90 (which is "used" in the subroutine), I find
!============================================================================!
!============================================================================!
!---------------------------------------------------------------------------!
! Site type:
! The following are the patch level arrays that populate the current site.
!---------------------------------------------------------------------------!
type sitetype
integer :: npatches
! The global index of the first cohort in all patches
integer,pointer,dimension(:) :: paco_id
! The number of cohorts in each patch
integer,pointer,dimension(:) :: paco_n
! Global index of the first patch in this vector, across all patches
! on the grid
integer :: paglob_id
! The patches containing the cohort arrays
type(patchtype),pointer,dimension(:) :: patch
Etc etc - this goes one for another 500 lines or so.
So to get to the point, it seems like the original subroutine needs an explicit interface for its procedures in order to be able to use the (dummy) argument csite. Again, I am SO NEW to Fortran, but I am really trying to understand how it "thinks". I have been searching what it means to have an explicit interface, when (and how!) to use it etc. But I can't figure out how it applies in my case. Should I maybe use a different compiler (Intel?). Any hints?
Edit: So csite is declared a target in all procedures and from the declaration type(site type) contains a whole bunch of pointers, as specified in sitetype. But sitetype is being properly used from another module (ed_state_vars.f90) in all procedures. So I am still confused why it gives me the explicit interface error?
"explicit interface" means that the interface to the procedure (subroutine or function) is declared to the compiler. This allows the compiler to check consistency of arguments between calls to the procedure and the actual procedure. This can find a lot of programmer mistakes. You can do this writing out the interface with an interface statement but there is a far easier method: place the procedure into a module and use that module from any other entity that calls it -- from the main program or any procedure that is itself not in the module. But you don't use a procedure from another procedure in the same module -- they are automatically known to each other.
Placing a procedure into a module automatically makes its interface known to the compiler and available for cross-checking when it is useed. This is easier and less prone to mistakes than writing an interface. With an interface, you have to duplicate the procedure argument list. Then if you revise the procedure, you also have to revise the calls (of course!) but also the interface.
An explicit interface (interface statement or module) is required when you use "advanced" arguments. Otherwise the compiler doesn't know to generate the correct call
If you have a procedure that is useed, you shouldn't describe it with external. There are very few uses of external in modern Fortran -- so, remove the external attributes, put all of your procedures into a module, and use them.
I ran into the same problems you encountered whilst I was trying to install ED2 on my mac 10.9. I fixed it by including all the subroutines in that file in a module, that is:
module mymodule
contains
subroutine update_budget(csite,lsl,ipaa,ipaz)
other subroutines ecc.
end module mymodule
The same thing had to be done to some 10 to 15 other files in the package.
I have compiled all the files and produced the corresponding object files but now I am getting errors about undefined symbols. However I suspect these are independent of the modifications so if someone has the patience this might be a way to solve at least the interface problem.
I have a question regarding best practices of model/variable usage:
Let's assume I have a module containing a few variable/parameter definitions and some subroutines that use these variables.
I do not need to explicitly use these variables in the subroutines since they are inherited from the parent module - but would it be better practice to do so?
Example:
module test
implicit none
integer, parameter :: a = 1
real :: x
contains
subroutine idk(y,z)
real, intent(in) :: y
real, intent(out) :: z
if(a .eq. 1) then
z = x*y + 5.
else
z = x*y - 5.
end if
end subroutine idk
end module test
The above example should work just fine but would it be better to add
use test, only: a,x
to the declaration part of subroutine idk?
In my reasoning, there are two main points here:
1) Pro: Explicitly adding this line let's me easily see which variables are actually needed in the subroutine.
In many cases, the module contains quite a number of variables but only a few are needed in each subroutine. So for reasons of better comprehensibility, it would be beneficial to add this line.
BUT
2) Contra: In quite a few cases, one needs a lot of the variables/parameters declared above (sometimes numbering more than 100 parameters). Explicitly using these at the beginning of the subroutine just unnecessarily clutters the code, reducing the readability of the code.
Point 1 matters mostly if only a few variables need to be included, whereas point 2 is only important if many variables need to be included. But I think it would be silly to do one thing for few variables and another for many - once you have picked a convention, you should stick to it IMHO...
Is there a best practice regarding this?
Addition:
Alternatively, one could declare the subroutine as
subroutine idk(b,w,y,z)
and then call it as idk(a,x,y,z).
On the one hand, this would give me greater flexibility if I later decide that I want to use idk with other variables.
On the other hand, it also increases the risk of mistakes if I change something later (say, I realize I don't need parameter a as a condition but parameter c. In the first cases, I simply switch out a -> c in the subroutine. But in the last case, I need to change every call to idk(c,...). If there are a lot of these calls, this is prone to mistakes)
I would really appreciate your input! Thank you!
There is absolutely no reason to use the module currently being defined. It is illegal. It may happen to compile if the module was compiled before and the compiler can find the .mod file, but file, but other than that it is wrong.
You should expect error such as
ifort -c assoc.f90
assoc.f90(10): error #6928: The module-name on a USE statement in a program unit cannot be the name of any encompassing scoping unit. [TEST]
use test
------^
The module subroutine gets the variables from the host module through host association and the use statement is for use association. These are two different things and should not be mixed.
If you want to avoid global variables, pass them as arguments. This is a general advice. What is best depends on each case and the programmer and cannot be answered generally.
Are there any "general rules" as to when one is preferable to the other?
The context of this question is: I asked a different question regarding host association yesterday (link) and in the comments, I was advised to use host association with caution. The reason being that through host association, it is easy to inadvertently modify variables since the subroutines have unrestricted access to all variables that are declared in the module.
To illustrate this, I will use the following code example:
module mod
implicit none
real :: x
contains
subroutine sub(y)
use other_mod, only: a
real, intent(out) :: y
y = a + x
a = a + 1.
x = x + 1.
end subroutine sub
end module mod
Both aand x are modified in sub. But for x, I need to go through all the code to see this. That a is used in sub (and possibly modified) can be seen easily by looking at the declaration part of sub.
In this sense, it seems preferable to have two kinds of modules:
A module or modules only containing variable declarations (which are then used when needed)
Modules that only contain procedures and possibly parameter declarations but no variable declarations
This gets rid of host association for variables altogether.
But this doesn't seem practical for a number of reasons:
I might have a dozen subroutines using (and modifying) the same variables in one module. Having to use these variables everytime clutters the code, especially if there are a lot of them (say a few hundred).
Seperating the declaration of a variable from where it is actually used seems to make the code less comprehensible:
Either, one creates one giant control file containing all the declarations. This could be quite confusing if the code is large and uses many variables.
Or, one creates a seperate control file for every module (or group of modules, if they depend on the same content). This would make the code itself better comprehensible, since using the variables immediately shows where they are coming from. But it would complicate the structure of the code, creating a vastly more complicated file structure (and accompanying dependency structure).
In the end, all of this boils down to: When is it more sensible to put the declaration of variables in the same module in which they are used (so that they are used by host association) and when is it more sensible to outsource the declaration to a seperate module (so that the variables will be used via use association when they are needed)?
Are there any general guidelines or should this be decided on a case by case basis? And if it is case by case, what are the reasons to go for one over the other?
Fortran provides several ways to create, store, use, and pass data between different "program units": the main program, external procedures, and modules.1 As you know, each program unit can contain internal procedures - which, through host association, have access to any variable or procedure contained within the host. This is often seen as an advantage. As mentioned already by #HighPerformanceMark in his comment, the general guideline for when to use host-association or use-association is:
use host-association when variables are only (or mainly) used by routines declared in the same module, and use use-association when you want to define variables to be used in many modules
From your comments, it sounds like most or all of the host variables in your main program are accessed by each internal procedure (about a dozen or so subroutines). If that's the case, then host-association seems like a very reasonable option, and there's really no need to pass in arguments to each subroutine explicitly. On the other hand, if each subroutine actually uses only a subset of the variables, then it might be reasonable to get more explicit about it.
Like you, I am generally uncomfortable with using variables within a procedure that haven't been declared in an argument list. This is partly because I like how the list of args is self-documenting, and it helps me to reason about the code and how data is manipulated within it. This is even more true when collaborating with other workers, or if I've spent some time away from the code and my memory of it has faded. However, I've discovered there is little reason to avoid host association altogether, as long as you are aware of how it works and have a strategy.
In fact, I tend to use internal procedures and host-association quite often, especially for short functions/subroutines. I find it helpful to loosely think of the host as the "object", its variables as "attributes", and any internal procedures very much like the object's "methods" that do the work. Of course, that's simplifying things, but that's really the point.
For more complex programs I reduce the amount of host-association from the "main" program itself, which then exists primarily to call the various subroutines in the proper order and context. In this case, we can take advantage of use-association and choose to use module entities (such as procedures, variables, types, parameters) directly within the program unit that needs them. We can further restrict access to only those module entities that are needed with only:. This aids readability, the data flow is clearly indicated, and I find that updating the code later is more straightforward. You know, inheritance, encapsulation, and whatnot...but Fortran style. Which is actually pretty good.
Here's an example program structure that works for me and the moderately-sized projects I've worked on in Fortran. I like to keep my widely-used (static) parameters in a separate module (or modules, if grouped according to function). I keep derived types and type-bound procedures in another separate module(s). If it's useful, I make certain module entities private, so that they are not accessible from other program units. And I guess that's it.
module params
implicit none
public !! All items public/accessible by default.
integer, parameter :: dp = kind(0.d0)
integer, parameter :: nrows = 3
real(dp), parameter :: one=1.0_dp, two=2.0_dp
...
end module params
module types
use params, only: dp, nrows
implicit none
public !! Public by default.
private :: dim2
...
integer, parameter :: dim2 = 3
...
type :: A
integer :: id
real(dp), dimension(nrows,dim2) :: data
contains
procedure, pass :: init
end type A
...
contains
subroutine init(self, ...)
...
end subroutine init
...
end module types
module utils
implicit none
private !! Private by default.
public :: workSub1, workSub2, subErr
...
integer,save :: count=0 !! Accessible only to entities in this module.
...
contains
subroutine workSub1(...)
...
end subroutine workSub1
subroutine workSub2(...)
...
end subroutine workSub2
subroutine subErr(...)
...
end subroutine subErr
end module utils
program main
!! An example program structure.
use params, only: dp
implicit none
real(dp) :: xvar, yvar, zvar
integer :: n, i
logical :: rc
call execute_work_subroutines()
contains !! Internal procs inherit all vars declared or USEd.
subroutine execute_work_subroutines()
use types, only: A
type(A) :: DataSet
!! begin
call DataSet%init(i)
do i = 1,n
call workSub1(xvar,yvar,zvar,A,i,rc)
if (rc) call subErr(rc)
call workSub2(A,rc)
if (rc) call subErr(rc)
enddo
end subroutine execute_work_subroutines
end program main
1There are also submodules, but I am not familiar with them and don't want to give misleading info. They do seem useful for logically separating large modules.
Is currying for functional programming the same as overloading for OO programming? If not, why? (with examples if possible)
Tks
Currying is not specific to functional programming, and overloading is not specific to object-oriented programming.
"Currying" is the use of functions to which you can pass fewer arguments than required to obtain a function of the remaining arguments. i.e. if we have a function plus which takes two integer arguments and returns their sum, then we can pass the single argument 1 to plus and the result is a function for adding 1 to things.
In Haskellish syntax (with function application by adjacency):
plusOne = plusCurried 1
three = plusOne 2
four = plusCurried 2 2
five = plusUncurried 2 3
In vaguely Cish syntax (with function application by parentheses):
plusOne = plusCurried(1)
three = plusOne(2)
four = plusCurried(2)(2)
five = plusUncurried(2, 3)
You can see in both of these examples that plusCurried is invoked on only 1 argument, and the result is something that can be bound to a variable and then invoked on another argument. The reason that you're thinking of currying as a functional-programming concept is that it sees the most use in functional languages whose syntax has application by adjacency, because in that syntax currying becomes very natural. The applications of plusCurried and plusUncurried to define four and five in the Haskellish syntax merge to become completely indistinguishable, so you can just have all functions be fully curried always (i.e. have every function be a function of exactly one argument, only some of them will return other functions that can then be applied to more arguments). Whereas in the Cish syntax with application by parenthesised argument lists, the definitions of four and five look completely different, so you need to distinguish between plusCurried and plusUncurried. Also, the imperative languages that led to today's object-oriented languages never had the ability to bind functions to variables or pass them to other functions (this is known as having first-class functions), and without that facility there's nothing you can actually do with a curried-function other than invoke it on all arguments, and so no point in having them. Some of today's OO languages still don't have first-class functions, or only gained them recently.
The term currying also refers to the process of turning a function of multiple arguments into one that takes a single argument and returns another function (which takes a single argument, and may return another function which ...), and "uncurrying" can refer to the process of doing the reverse conversion.
Overloading is an entirely unrelated concept. Overloading a name means giving multiple definitions with different characteristics (argument types, number of arguments, return type, etc), and have the compiler resolve which definition is meant by a given appearance of the name by the context in which it appears.
A fairly obvious example of this is that we could define plus to add integers, but also use the same name plus for adding floating point numbers, and we could potentially use it for concatenating strings, arrays, lists, etc, or to add vectors or matrices. All of these have very different implementations that have nothing to do with each other as far as the language implementation is concerned, but we just happened to give them the same name. The compiler is then responsible for figuring out that plus stringA stringB should call the string plus (and return a string), while plus intX intY should call the integer plus (and return an integer).
Again, there is no inherent reason why this concept is an "OO concept" rather than a functional programming concept. It simply happened that it fit quite naturally in statically typed object-oriented languages that were developed; if you're already resolving which method to call by the object that the method is invoked on, then it's a small stretch to allow more general overloading. Completely ad-hoc overloading (where you do nothing more than define the same name multiple times and trust the compiler to figure it out) doesn't fit as nicely in languages with first-class functions, because when you pass the overloaded name as a function itself you don't have the calling context to help you figure out which definition is intended (and programmers may get confused if what they really wanted was to pass all the overloaded definitions). Haskell developed type classes as a more principled way of using overloading; these effectively do allow you to pass all the overloaded definitions at once, and also allow the type system to express types a bit like "any type for which the functions f and g are defined".
In summary:
currying and overloading are completely unrelated
currying is about applying functions to fewer arguments than they require in order to get a function of the remaining arguments
overloading is about providing multiple definitions for the same name and having the compiler select which definition is used each time the name is used
neither currying nor overloading are specific to either functional programming or object-oriented programming; they each simply happen to be more widespread in historical languages of one kind or another because of the way the languages developed, causing them to be more useful or more obvious in one kind of language
No, they are entirely unrelated and dissimilar.
Overloading is a technique for allowing the same code to be used at different types -- often known in functional programming as polymorphism (of various forms).
A polymorphic function:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
Here, map is a function that operates on any list. It is polymorphic -- it works just as well with a list of Int as a list of trees of hashtables. It also is higher-order, in that it is a function that takes a function as an argument.
Currying is the transformation of a function that takes a structure of n arguments, into a chain of functions each taking one argument.
In curried languages, you can apply any function to some of its arguments, yielding a function that takes the rest of the arguments. The partially-applied function is a closure.
And you can transform a curried function into an uncurried one (and vice-versa) by applying the transformation invented by Curry and Schonfinkel.
curry :: ((a, b) -> c) -> a -> b -> c
-- curry converts an uncurried function to a curried function.
uncurry :: (a -> b -> c) -> (a, b) -> c
-- uncurry converts a curried function to a function on pairs.
Overloading is having multiple functions with the same name, having different parameters.
Currying is where you can take multiple parameters, and selectively set some, so you may just have one variable, for example.
So, if you have a graphing function in 3 dimensions, you may have:
justgraphit(double[] x, double[] y, double[] z), and you want to graph it.
By currying you could have:
var fx = justgraphit(xlist)(y)(z) where you have now set fx so that it now has two variables.
Then, later on, the user picks another axis (date) and you set the y, so now you have:
var fy = fx(ylist)(z)
Then, later you graph the information by just looping over some data and the only variability is the z parameter.
This makes complicated functions simpler as you don't have to keep passing what is largely set variables, so the readability increases.
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.