1

I am trying to add access restrictions to some of the variables (using private attribute) in a module but I need to use those variables in subsequent invocations of routines within that module:

module MyMod

  private 
  integer,allocatable :: A(:)

  public :: init,calc

contains

  subroutine init()

    ! allocating and initializing A

  end subroutine init

  subroutine calc()

    ! Using A

  end subroutine

 end module

Questions:

  1. Is this true that the private variable will not be in the scope of the program which uses this module.

  2. If the answer to 1 is yes, then I would think that I can use save attribute for this variable. Please correct me if I am wrong?

  3. Is this the proper way to perform this task?

francescalus
  • 30,576
  • 16
  • 61
  • 96
Amir
  • 335
  • 2
  • 11
  • I'm not sure about your third question. Could you elaborate on this? What are you trying to achieve? – Alexander Vogt Dec 15 '15 at 19:36
  • Thank for you reply. I understand that the variable is private to module. My major question is: I initialize it using init() which is called from the program (say main.F90) which uses the module. Then, the routine calc() is called from main.F90. Now, in general, if the scope of the variable A is lost because of having the private attribute, it would not be safe to use A in calc(). – Amir Dec 15 '15 at 19:41

3 Answers3

3

Yes, if you put a private statement into your module without any further specification, you set the default accessibility to private.

For the first question, the Fortran 2008 Standard (Cl. 4.5.2.2 §3) states that:

If a type definition is private, then the type name, and thus the structure constructor (4.5.10) for the type, are accessible only within the module containing the definition, and within its descendants.

So A will not be accessible from anywhere outside the module or submodule (descendant).

For the second question, yes - you can use save here. (This is not related to the accessibility attribute). In fact, starting with Fortran 2008, this is implied for module variables, see for the Fortran 2008 Standard (Cl. 5.3.16 §4) [thanks @francescalus]:

A variable, common block, or procedure pointer declared in the scoping unit of a main program, module, or submodule implicitly has the SAVE attribute, which may be confirmed by explicit specification [...]

If I understood your third question correctly, it is related to the initialization. You could realize this with a function/subroutine to which you pass an array for initialization:

module MyMod
! ...
contains
! ...
subroutine init( A_in )
  implicit none
  integer, intent(in) :: A_in(:)

  ! allocating and initializing A
  allocate( A(size(A_in)) )
  A = A_in
end subroutine

end module

Inside init() you create a copy of A_in which is only accessible within the module. As long as calc() is part of the module (or a submodule thereof), it has full access to A.

Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
1

To add to the answer by Alexander Vogt an implication of the save attribute.

This attribute gives precisely the effect you seem to be after (from F2008 5.3.16):

The SAVE attribute specifies that a local variable of a program unit or subprogram retains its association status, allocation status, definition status, and value after execution of a RETURN or END statement unless [something not applicable here]

In your example, A is a local variable of the module (and so a program unit) MyMod.

This means that, after the call to init which, presumably, allocates A and sets values that status is retained after the subroutine returns. Those values are then available come the call to calc. Both init and calc, of course, refer to the same A through host association.

You mention Fortran 90, so there is a subtle change (again as mentioned in that other answer). Before Fortran 2008 module variables would require the save attribute explicitly giving in some circumstances for this effect to come about. There's no harm in giving the save attribute explicitly if you aren't sure how your compiler treats the code (and some would say it's good practice, anyway).

Community
  • 1
  • 1
francescalus
  • 30,576
  • 16
  • 61
  • 96
1

This is another way of accomplishing what you want to do while avoiding the 'save'.

module MyMod

  private
  public :: myType, init

  type myType
    private
    integer, allocatable :: A(:)
  end type myType

contains

  subroutine init(obj, n)

    type(myType), intent(inout) :: obj
    integer, intent(in) :: n

    allocate(obj%A(n), source=-9999999)

  end subroutine init

end module MyMod

program test

  use MyMod, only: myType, init 

  type(myType) :: m ! m is an opaque object

  call init(m, 10)

end program test

In this example, m is an opaque object - I can create the object, pass it around, but not access its contents (the array A in this case). This way, I am hiding my data. As long as my object m is in scope, I can operate on the data hidden in the object through routines contained in the module myMod.

If you have access to a modern compiler that supports Fortran 2003, you can rewrite the module as

module MyMod

  private
  public :: myType

  type myType
    private
    integer, allocatable :: A(:)
  contains
    procedure, public :: init
  end type myType

contains

  subroutine init(obj, n)

    class(myType), intent(inout) :: obj
    integer, intent(in) :: n

    allocate(obj%A(n), source=-9999999)

  end subroutine init

end module MyMod

program test

  use MyMod, only: myType

  type(myType) :: m ! m is an opaque object                                                         

  call m%init(10)

end program test
pch
  • 72
  • 3
  • Thanks for your suggestion. I would certainly try to use this idea which seems to stem from object-oriented features of F2003. Can one think of any difference between this method and using save attribute performance-wise? – Amir Dec 16 '15 at 14:55
  • Yes, F2003 introduced procedure encapsulation in a derived type. – pch Dec 16 '15 at 15:23
  • I have never tested the performance of 'save'd variables. But using the save attribute is not considered to be a good programming practice. [Here](http://stackoverflow.com/questions/2893097/fortran-save-statement#comment7521015_2893097) is a comment that says it better than I could. – pch Dec 16 '15 at 15:30