Attempt to make a variable defined in a Fortran Module editable only by specific subroutines contained by said Module

Hi.

I’ve been using Fortran for some time now due to my course requirements. I’m still not good at it, but I’m trying to improve by reading through the threads posted here and by taking on Metcalf’s and Chapman’s books (latest editions of both).

One of the questions I have at the moment is the following: suppose that I want a given variable to be accessible to all procedures contained by a module and to the main program which uses this module. Normally, I’d have to transfer its value to all of these subroutines via procedure arguments, but I learned that module parameters could be a good solution to this problem – and it was.

However, this “global variable” I want to use needs to be defined by a specific subroutine first and, this is a problem, because I don’t want other procedures to mistakenly change that variable’s value. I’ve been taking care of how I use my global variables for now, but is there any way I can “lock” a variable defined in the module to be editable only by specific subroutines? Example below:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Module:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module program_module
use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64
implicit none

integer :: n, m


contains

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Subroutine 1:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine sub1()

print*, "[Subroutine 1]: Insert the value of n"
read(*,*) n
print*, "[Subroutine 1]: n = ",n

end subroutine sub1

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Subroutine 2:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine sub2()

print*, "[Subroutine 2]: n = ",n

n=2

print*, "[Subroutine 2]: The value of n has been changed to n = ", n

    
end subroutine sub2

end module program_module


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Main program
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program program_main
use, non_intrinsic :: program_module
implicit none

call sub1()
call sub2()

print*, "[Main program]: the current value of n is n = ",n

end program program_main

OUTPUT:

 [Subroutine 1]: Insert the value of n
-8
 [Subroutine 1]: n =           -8
 [Subroutine 2]: n =           -8
 [Subroutine 2]: The value of n has been changed to n =            2
 [Main program]: the current value of n is n =            2

I want for n to be editable only by Subroutine 1, and the compiler should throw an error for every other program unit (including the main program) which attempts to modify it. Is it possible? Are there any alternatives available?

Thanks.

A protected module variable is only editable by the module it is defined in. For example

module mymodule1
  implicit none
  integer, protected :: a
end module

module mymodule2
  implicit none
contains
  subroutine dostuff()
    use mymodule1, only: a
    a = 10
  end subroutine
end module

During compilation the error is thrown

test.f90:11:4:

   11 |     a = 10
      |    1
Error: Variable 'a' is PROTECTED and cannot appear in a variable definition context (assignment) at (1)
1 Like

Thank you, @nicholaswogan.

I knew about the protected statement/attribute, but I somehow hadn’t thought about using separate modules just for these constants and “approved” subroutines.