Completely apart from the discussions about whether programming languages should be case sensitive or not [1] [2], what would be a good naming convention for languages that are case-insensitive?
Specifically I'm working in Fortran, but most commonly available style guides are for languages that are case sensitive, and thus recommend naming conventions like:
Class/Type names are CapitalizedWords
Method/function names are firstWordNotCapitalized
Variables are lower_case_with_underscores
Constants are ALL_CAPS_WITH_UNDERSCORES
But in case insensitive languages, everything is effectively ALL CAPS, so the only way to legibly have multi-word names is ALL_CAPS_WITH_UNDERSCORES. So is my only option for distinguishing between the "kinds" of names to go back to Hungarian Notation?
Class/Type names are APPENDED_WITH_T
Method/function/subroutine names are APPENDED_WITH_{F or S}
Module names are APPENDED_WITH_M
Variable names are NOT_APPENDED (and constants are just variables)
Name collisions are a major problem in Fortran, since even the name of a module will cause a collision with a variable name, or a derived type name. Is this a case where, even though everyone says Hungarian notation is a bad idea, it makes sense in this instance?
Edit:
As a response to a comment, for example, in a case sensitive language (C++ for example) I'd be able to do something like this:
in a file (i.e. module) called Logger.cc:
class Logger {
Logger(some type, of arguments) {...}
log(some argument) {...}
}
in another file somewhere:
#include "Logger.h"
void aFunctionThatCreatesALogger() {
...
Logger logger = new Logger(with, arguments)
...
}
void functionThatLogs(Logger logger) {
...
logger.log(thing)
...
}
And the equivalent Fortran might look like:
in a file (i.e. module name Logger.f90):
module Logger
type Logger
contains
procedure :: log
end type
contains
type(Logger) function Logger(some, arguments) result(logger)
logger%some = some
logger%arguments = arguments
end function Logger
subroutine log(logger, argument)
class(Logger) :: logger
type(some), intent(in) :: argument
...
end subroutine log
end module Logger
in another file somewhere:
module someModule
use Logger, only: Logger, Logger
contains
subroutine routineThatCreatesALogger()
type(Logger) :: logger
...
logger = Logger(with, arguments)
...
end subroutine routineThatCreatesALogger
subroutine routineThatLogs(logger)
type(Logger), intent(in) :: logger
...
call logger%log(thing)
...
end subroutine routineThatLogs
end module someModule
but of course the name collisions between the module name, the type name, the "constructor" function, and my variable name are all a problem, because Fortran can't tell the difference between case and/or context of use.
I fully understand that any suggestions will be highly subjective, but I'd still like to here if anybody has a better/different suggestion than Hungarian notation.
I'm pretty sure that the major reason for the case variations in naming conventions is to give a hint to the human reader as to what that name denotes, not to avoid name clashes.
So unless your compiler really supports only uppercase names, for the most part you can adopt the usual conventions even in case-insensitive languages.
If name clashing really begins to be a problem, using prefixes or suffixes (the latter are most likely preferable) might be ok, but I wouldn't make it a general, compulsory convention, but just a thing to use when it's needed.
And (especially) if you do indeed use them only occasionaly, it's most likely better to use something self-explanatory rather than single letters or strange acronyms.
Your examples aFunctionThatCreatesALogger or functionThatLogs, if they were meant as name proposals, might actually not be the monstrosity that they seem at first glance (if used occasionally), but I'd argue that it's much better to start with the most relevant term (log), and put the eventual specifiers at the end (e.g. loggerCreatingFunction or loggerFunction).
Whether to use a full, expanded term, an abbreviation/acronym or even a single letter should depend mostly on whether most developers use tools with good auto-completion or not.
But you should always be wary to use these specifiers, it's most likely better to avoid things like that as much as possible.
So if you wrote code which declares names that use them, think thrice before committing it.
Note that I don't know Fortran (but I did work a lot with another case-insensitive language).
I'm pretty sure I'm going to stick with my initial idea. Append _t to type names, and in situations where a module contains something with the same name, append _module to module names. Other than that I'll stick with the common convention:
Class/Type names are CapitalizedWords
Method/function names are firstWordNotCapitalized
Variables are lower_case_with_underscores
Constants are ALL_CAPS_WITH_UNDERSCORES
That should avoid the vast majority of naming collisions and (hopefully) produce readable code.
The above Fortran example would then become:
module Logger_module
type Logger_t
contains
procedure :: log
end type
contains
type(Logger_t) function createLogger(some, arguments) result(logger)
logger%some = some
logger%arguments = arguments
end function createLogger
subroutine log(logger, argument)
class(Logger_t) :: logger
type(some_t), intent(in) :: argument
...
end subroutine log
end module Logger
and
module some_module
use Logger_module, only: Logger_t, createLogger
contains
subroutine routineThatCreatesALogger()
type(Logger_t) :: logger
...
logger = createLogger(with, arguments)
...
end subroutine routineThatCreatesALogger
subroutine routineThatLogs(logger)
type(Logger_t), intent(in) :: logger
...
call logger%log(thing)
...
end subroutine routineThatLogs
end module some_module
Of course this ignores the question as to whether you should use a convention that relies on case in a case insensitive language, but that's the kind of question that really invites opinionated and subjective arguments, so I won't ask it.
Related
I use the Intel Visual Fortran. According to Chapmann's book, declaration of function type in the routine that calls it, is NECESSARY. But look at this piece of code,
module mod
implicit none
contains
function fcn ( i )
implicit none
integer :: fcn
integer, intent (in) :: i
fcn = i + 1
end function
end module
program prog
use mod
implicit none
print *, fcn ( 3 )
end program
It runs without that declaration in the calling routine (here prog) and actually when I define its type (I mean function type) in the program prog or any other unit, it bears this error,
error #6401: The attributes of this name conflict with those made accessible by a USE statement. [FCN] Source1.f90 15
What is my fault? or if I am right, How can it be justified?
You must be working with a very old copy of Chapman's book, or possibly misinterpreting what it says. Certainly a calling routine must know the type of a called function, and in Fortran-before-90 it was the programmer's responsibility to ensure that the calling function had that information.
However, since the 90 standard and the introduction of modules there are other, and better, ways to provide information about the called function to the calling routine. One of those ways is to put the called functions into a module and to use-associate the module. When your program follows this approach the compiler takes care of matters. This is precisely what your code has done and it is not only correct, it is a good approach, in line with modern Fortran practice.
association is Fortran-standard-speak for the way(s) in which names (such as fcn) become associated with entities, such as the function called fcn. use-association is the way implemented by writing use module in a program unit, thereby making all the names in module available to the unit which uses module. A simple use statement makes all the entities in the module known under their module-defined names. The use statement can be modified by an only clause, which means that only some module entities are made available. Individual module entities can be renamed in a use statement, thereby associating a different name with the module entity.
The error message you get if you include a (re-)declaration of the called function's type in the calling routine arises because the compiler will only permit one declaration of the called function's type.
I have a program like this
program
call one()
contains one()
some vars
contains two()
use the vars of one
define its own vars
contains three()
use the vars of both one and two
This doesn't compile because Fortran allows only the first contains statement.
I used this design to avoid passing and retyping all the variables of one() into two() and three().
How can I rewrite the program so that the variable sharing is achieved?
I cannot define all the variable before the statement call one().
The code will be to hard to manage, I need the feature :
parent subroutine cannot access internal subroutine variables.
Maybe a solution is to use pointer
call one(pointer_to_two)
then define the routine two() in its own module.
But I find this design complicate with my limited Fortran skills.
And I'm worried it will impact performance.
Should I use a common block?
I use the latest dialect of Fortran with the Intel compiler.
Below is 'compilable' example.
program nested_routines
call one()
contains
subroutine one()
integer :: var_from_one = 10
print *, 1
call b()
contains
subroutine two()
integer :: var_from_two = 20
print *, 2, var_from_one
call c()
contains
subroutine three()
print *, 3, var_from_one, var_from_two
end subroutine
end subroutine
end subroutine
end module
I recommend placing your procedures (subroutines and functions) into a module after a single "contains" and using that module from your main program. The local variables of each procedure will be hidden their callers. The way that this differs from your goals is that you have to redeclare variables. I dislike the inheritance of all variables in a subroutine contained in another because it is possible to mistakenly reuse a variable. If you have a few variables that are shared across many procedures, perhaps the appropriate design choice is to make them global. With Fortran >=90, a module variable is better method for a global variable than common blocks. If you have variables that are communicated between a limited number of procedures, it is generally better to use arguments because that makes the information flow clearer.
this might be possible if there is a separate module for each of the functions specific variables and a separate module for each function implementation
watch out for the order of the module compilation, according to the usage hierarchy necessity
also, i have no idea on the performance effect of doing this
module m1_var
implicit none
contains
end module m1_var
!========================================================================================================================
module m2_var
implicit none
contains
end module m2_var
!========================================================================================================================
module m3_var
implicit none
contains
end module m3_var
!========================================================================================================================
module m3_sub
implicit none
contains
subroutine s3()
use m2_var !to see varibles
!arguments
!local
!allocation
!implementation
end subroutine s3
end module m3_sub
!========================================================================================================================
module m2_sub
implicit none
contains
subroutine s2()
use m3_sub
use m1_var
!arguments
!local
!allocation
!implementation
call s3
end subroutine s2
end module m2_sub
!========================================================================================================================
module m1_sub
use m1_var
implicit none
contains
subroutine s1()
use m2_sub
!arguments
!local
!allocation
!implementation
! call s2
end subroutine s1
end module m1_sub
!========================================================================================================================
program nestmoduse
use m1_sub
implicit none
call s1
end program nestmoduse
Currently in my program I have several common blocks spread across several subprograms and functions. I sometimes forget to change all instances of a common block as I add variables to it. I want to make these common blocks into modules so I can add and remove variables to the module in one place without worrying about updating all instances of the module across my subprograms.
Do I need to include 'use' statements in the program that initializes the variables in the module or do I include the program in the module? I normally would use common blocks for this but am trying to implement modules because I think they will help my code remain readable as complexity increases.
NOTE: Some values of the variables in the modules need to be able to change as they are passed from one program to another.
I tried to write a simplified test program to become acquainted with modules but could not get it to work. I am familiar with fortran 77 but have never used modules before. I appreciate any help or advice.
I am using gfortran 4.6.1
Main.f
program main
use Words
use Vals
double precision x,y,z
character*5 Greet
integer i
Greet = 'Hello'
x = 4.1
y = 5.2
z = 10.0
i = 3
call foo ()
end program main
subroutine foo ()
use Words
use Vals
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
module Words
character*5 Greet
save
end module
module Vals
double precision x,y
integer int
save
end module
You only need one instance of a module. You make it known to any main program or procedure (subroutine or function) that uses it with a use statement. If you have a subroutine that sets values then, like any other, it has to have a use statement. If are are setting initial values you can do so in the declaration. If the module is used by the main program then it will always be in scope and the values of the variables will persist throughout the run of the program. If the module is only used by procedure, in principle the module will go out of scope when none of those procedures are in the call chain and the compiler is allowed to forget the values of the module variables. (It is doubtful that any Fortran compiler actually does this.) This can be prevented by declaring each variable with SAVE. SAVE is implicit if you declare the variable with an initial value.
Normally you have to compile the modules first before they are used so that the compiler "knows" about them when it encounters the use statement. This is done either by putting them first in the file or compiling their files first. Here is your example reordered:
module Words
character*5 Greet
save
end module
module Vals
double precision x,y
integer i
save
end module
module my_subs
contains
subroutine foo ()
use Words
use Vals
double precision :: z
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
end module my_subs
program main
use Words
use Vals
use my_subs
Greet = 'Hello'
x = 4.1
y = 5.2
i = 3
call foo ()
end program main
There are a couple of reasons why your code will not compile:
You have your modules positioned after your main program, which means they will not have been compiled by the time you use them there. Either put these in separate files and compile them before the main program, or put them before the main program.
You re-declare variables from your module in the main program, which the compiler will interpret as a name conflict. All module variables with the public attribute (which is the default) will become available in the scope where you use the module; this is called "use association". In other words, use vals is enough to make x, y and int available.
Additionally, modules are more like singleton objects rather than just data containers. They can also contain procedures, listed after a contains statement, which aids grouping variables and related procedures together. An example would be grouping your two modules into one, along with subroutine foo:
module vals
implicit none
double precision :: x = 4.1, y = 5.2
integer :: i = 3
character(5) :: greet = 'Hello'
contains
subroutine foo()
double precision :: z ! New local variable
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
end module
Above, I have used the "new" :: double colon operator, which allows declaring and initialising multiple variables at once. Since module variables are already save'd implicitly, this is just fine.
Alternatively, if these modules are intended to be separate, you can also have contains sections in your main program (or any subprogram) and place the subroutine there. The advantage is that procedures declared in such a way always have explicit interfaces, which greatly benefits error diagnosis by the compiler and is even required in certain newer cases. This is one of the main improvements of F90, since F77 only dealt with external subprograms and implicit interfaces.
The simplest way to do common blocks is to have one include file per common block and make all your declarations within the include file. That way, the common block is only ever declared in one place. The problem of having to convert the code to use modules then just magically disappears.
Also, if you are starting new code, prefixing the name of the common block variables with the same name as the named common block will make coding a lot easier. It is a pain initially and the prima donnas who have been coding for years will refuse to conform. The people who maintain the code will just find it so easy: no greps or groks. Just by looking at the name, you know which common block it comes from.
Keeping the same convention with modules also helps. If all routine names and variable names begin with the module name, then just by looking at the name, you know which module it comes from.
Is it possible in modern versions of Fortran to pass a kind parameter to a subprogram and to use this to 'cast' variables to this kind? As an example, in the following code I am trying to convert an default integer to an 16-bit integer before printing it.
program mwe
! Could use iso_fortran_env definition of int16, but I am stuck with
! old versions of ifort and gfortran.
! use, intrinsic :: iso_fortran_env, only : int16
implicit none
! 16-bit (short) integer kind.
integer, parameter :: int16 = selected_int_kind(15)
call convert_print(123, int16)
contains
subroutine convert_print(i, ikind)
implicit none
integer, intent(in) :: i
integer, intent(in) :: ikind
print*, int(i, ikind)
end subroutine convert_print
end program mwe
With this example code the Intel Fortran compiler complains that
mwe.f(24): error #6238: An integer constant expression is required in this context. [IKIND]
...
mwe.f(24): error #6683: A kind type parameter must be a compile-time constant [IKIND]
and gfortran complains
'kind' argument of 'int' intrinsic at (1) must be a constant
Using print*, int(i, int16) in place of print*, int(i, ikind) would of course work fine in this case. However, if convert_print were defined in a a module which does not define int16 then this would be useless.
Is there a way of passing a kind parameter as a constant to subprograms?
I have the same problem. I find extremely inconvenient that it is not allowed to pass the kind datatype as an argument to a procedures. In my case, I am writing write a subroutine to just read a matrix from a file and get the object in the data type that I want to. I had to write four different subroutines: ReadMatrix_int8(…), ReadMatrix_int16(…), ReadMatrix_int32(…) and ReadMatrix_int64(…) which are nothing but the same code with one single line different:
integer(kind=xxxx), allocatable, intent(out) :: matrix(:,:)
It would make sense to write only one subroutine and pass xxxx as an argument. If I find any solution I will let you know. But I am afraid that there is no better solution than writing the four subroutines and then writing an interface to create a generic procedure like:
interface ReadMatrix
module procedure ReadMatrix_int8
module procedure ReadMatrix_int16
module procedure ReadMatrix_int32
module procedure ReadMatrix_int64
end interface
As far as I can work out, what I am trying to do is expressly forbidden by the Fortran 2003 standard (PDF, 4.5 MB):
5.1.2.10 PARAMETER attribute
A named constant shall not be referenced unless it has been defined previously in the same statement, defined in a prior statement, or made accessible by use or host association.
Therefore is seems that I need to define a function for each conversion I wish to do, for example:
subroutine print_byte(i)
implicit none
integer, intent(in) :: i
print*, int(i, int8)
end subroutine print_byte
subroutine print_short(i)
implicit none
integer, intent(in) :: i
print*, int(i, int16)
end subroutine print_short
subroutine print_long(i)
implicit none
integer, intent(in) :: i
print*, int(i, int32)
end subroutine print_long
Obviously all of the above will have to be overloaded to accept different kinds of the input argument. This seems like a lot of work to get around not being able to pass a constant, so if someone has a better solution I am keen to see it.
This Intel expert gives an explanation and an elegant solution. I couldn't explain it better. A full cite follows:
"One day while I was wandering the aisles of my local grocery store, a woman beckoned me over to a table and asked if I would like to "try some imported chocolate?" Neatly arrayed on the table were packages of Lindt, Toblerone, and... Ghiradelli? I asked the woman if California had seceded from the Union, as Ghiradelli, despite its Italian name, hails from San Francisco. I suppose that from the vantage point of New Hampshire, California might as well be another country, much as depicted in that famous Saul Steinberg 1976 cover for The New Yorker, "View of the World from 9th Avenue".
(I've been warned that my blogs don't have enough arbitrary links - this should hold 'em for a while.)
Similarly, in Fortran (I'll bet you were wondering when I'd get to that), something can be so near yet seem so far away. A short time ago, I was writing a new module for Intel Visual Fortran to provide declarations for the Win32 Process Status API. This would contain declarations of types and constants as well as interface blocks for the API routines, some of which take arguments of the new type. The natural inclination is to write something like this:
MODULE psapi
TYPE sometype
some component
END TYPE sometype
INTERFACE
FUNCTION newroutine (arg)
INTEGER :: newroutine
TYPE (sometype) :: arg
END FUNCTION newroutine
END INTERFACE
END MODULE psapi
If you did and compiled it, you'd get an error that type sometype is undefined in the declaration of arg. "What? It's not undeclared, I can see it right above in the same module!" Well, yes and no. Yes, it's declared in the module and could be used anywhere in the module, except.. Except in interface blocks!
The problem is that interface blocks are a "window into the external routine" - they essentially duplicate the declarations you would see in the actual external routine, assuming that routine were written in Fortran. As such, they do not "host associate" any symbols from the enclosing scoping unit (the module in this case.)
In Fortran 90 and Fortran 95, the typical solution for this was to create a separate module, say, "psapi_types", containing all of the types and constants to be used, You'd then add a USE statement inside each function, just as you would have to in the hypothetical external routine written in Fortran. (If it were written in Fortran, the Doctor would slap your wrist with a wet punchcard and tell you to make the routine a module procedure, and then you wouldn't need to worry about this nonsense.) So you would end up with something like this:
MODULE psapi
USE psapi_types ! This is for the benefit of users of module psapi
INTERFACE
FUNCTION newroutine (arg)
USE psapi_types
INTEGER :: newroutine
TYPE (sometype) :: arg
...
Those of you who use Intel Visual Fortran know that in fact there's a giant module IFWINTY for this purpose, containing all of the types and constants for the other Win32 APIs. It's messy and inelegant, but that's what you have to do. Until now...
Fortran 2003 attempts to restore some elegance to this sorry situation, but to preserve compatibility with older sources, it couldn't just declare that interface blocks participate in host association. Instead, a new statement was created, IMPORT. IMPORT is allowed to appear in interface blocks only and it tells the compiler to import names visible in the host scope.
IMPORT is placed following any USE statements but before any IMPLICIT statements in an interface body (the FUNCTION or SUBROUTINE declaration). IMPORT can have an optional import-name-list, much like USE. Without one, all entities accessible in the host become visible inside the interface body. With a list, only the named entities are visible.
With IMPORT, my PSAPI module can look like the first example with the following change:
...
FUNCTION newroutine (arg)
IMPORT
INTEGER :: newroutine
TYPE(sometype) :: arg
...
I could, if I wanted to, use:
IMPORT :: sometype
to say that I wanted only that one name imported. Nice and neat and all in one module!
"But why are you telling me this?", you might ask, "That's a Fortran 2003 feature and Intel Fortran doesn't yet do all of Fortran 2003." True enough, but we keep adding more and more F2003 features to the compiler and IMPORT made it in back in August! So if you are keeping reasonbly current, you can now IMPORT to your heart's content and do away with the mess of a separate module for your types and constants.
If you want to know what other F2003 goodies are available to you, just check the Release Notes for each update. A full list of supported F2003 features is in each issue. Collect 'em all!"
can I declare intent variable in fortran module?
I want to make common module which can be called other subroutine
module fmod
real b
integer n, i
integer, dimension(6), intent(inout) :: indata1
real, dimension(7,8), intent(inout) :: indata2
end module fmod
subroutine temp_f(indata1, indata2)
use fmod
do i=1,8
print *, indata4(i)
end do
end
No, intent is for subroutine arguments, not module variables. Module variables are normally available to any entity that "use"s them. You can declare them to be "private" which will block their visibility outside of the module. Perhaps you are thinking of a module as an include file, which copies source code lines for compilation where they are copied. That is not the concept of a module ... it is an independent source code entity.
Although it is outside of the language standard, many Fortran compilers support the use of include files via "#include" starting in the first column. With some compilers use a filetype "F90" (upper-case). With others you have to use a compiler option to run the C-style pre-processor. There is a small risk that this usage will make your code less portable.