Go Back   Rhinocerus > Newsgroup > Newsgroup comp.lang.* 1 > Newsgroup comp.lang.fortran

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 04-24-2012, 07:23 AM
Marco Zannoni
Guest
 
Posts: n/a
Default Confusion with variables in modules

Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
Here's a simple example:

MODULE FOO_MODULE
IMPLICIT NONE
INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15)
REAL(KIND=NP), PARAMETER :: PI=3.14_NP
INTEGER :: K=0
END MODULE FOO_MODULE

PROGRAM FOO
USE foo_module
IMPLICIT NONE
REAL(KIND=NP) :: X, Y, Z
! Define Input Values
X=2.0_NP
Y=3.0_NP
! Print K
WRITE(*,*)'BEFORE) K=',K
! Call Subroutine
CALL FOO_FUN(X,Y,Z)
! Print K
WRITE(*,*)'AFTER) K=',K
END PROGRAM FOO

SUBROUTINE FOO_FUN(X,Y,Z)
USE foo_module
IMPLICIT NONE
REAL(KIND=NP), INTENT(IN) :: X, Y
REAL(KIND=NP), INTENT(OUT) :: Z
! Compute Output Z
Z=PI*X*Y
! Update K
K=K+1
END SUBROUTINE FOO_FUN

Compile:
ifort foo_module.f90 foo.f90 -o foo.x

Execution:
BEFORE) K= 0
AFTER) K= 1

So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous.

There is a way to permit to change the variables only explicitly?
This problem is related to the SAVE attribute?
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 04-24-2012, 07:34 AM
Phillip Helbig---undress to reply
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

In article
<10008744.644.1335252224047.JavaMail.geo-discussion-forums@vbbfr18>,
Marco Zannoni <marco.zannoni@gmail.com> writes:

> So, if I understand correctly, every subroutine that USE a module, can
> change the value of the variables defined into it. This can be useful,
> but also dangerous.


Right. That's pretty much one of the main points of modules.

> There is a way to permit to change the variables only explicitly?


What do you mean by "explicitly"? K=K+1 looks pretty explicit to me.

> This problem is related to the SAVE attribute?


No. The SAVE attribute means that the value remains defined until the
next call of the routine.

Reply With Quote
  #3 (permalink)  
Old 04-24-2012, 08:09 AM
Arjen Markus
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende:
> Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
> Here's a simple example:
>
> MODULE FOO_MODULE
> IMPLICIT NONE
> INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15)
> REAL(KIND=NP), PARAMETER :: PI=3.14_NP
> INTEGER :: K=0
> END MODULE FOO_MODULE
>
> PROGRAM FOO
> USE foo_module
> IMPLICIT NONE
> REAL(KIND=NP) :: X, Y, Z
> ! Define Input Values
> X=2.0_NP
> Y=3.0_NP
> ! Print K
> WRITE(*,*)'BEFORE) K=',K
> ! Call Subroutine
> CALL FOO_FUN(X,Y,Z)
> ! Print K
> WRITE(*,*)'AFTER) K=',K
> END PROGRAM FOO
>
> SUBROUTINE FOO_FUN(X,Y,Z)
> USE foo_module
> IMPLICIT NONE
> REAL(KIND=NP), INTENT(IN) :: X, Y
> REAL(KIND=NP), INTENT(OUT) :: Z
> ! Compute Output Z
> Z=PI*X*Y
> ! Update K
> K=K+1
> END SUBROUTINE FOO_FUN
>
> Compile:
> ifort foo_module.f90 foo.f90 -o foo.x
>
> Execution:
> BEFORE) K= 0
> AFTER) K= 1
>
> So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous.
>
> There is a way to permit to change the variables only explicitly?
> This problem is related to the SAVE attribute?


If you want to limit the accessibility and use these variables only as a
means to share information within the module, you can use the PRIVATE
attribute or statement:

integer, private :: k = 0

Then only routines in the module can access that particular variable k.
(Routines that use the module, could define an alternative variable called "k"
or acquire one from a different module, but this particular variable k will
no longer be visible.)

Regards,

Arjen
Reply With Quote
  #4 (permalink)  
Old 04-24-2012, 08:10 AM
robert.corbett@oracle.com
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

On Apr 24, 12:23*am, Marco Zannoni <marco.zann...@gmail.com> wrote:
> Hi, I'm confused about the behavior of the variables defined in a module,in particular regarding the possibility to change them.
> Here's a simple example:
>
> MODULE FOO_MODULE
> * IMPLICIT NONE
> * INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15)
> * REAL(KIND=NP), PARAMETER :: PI=3.14_NP
> * INTEGER :: K=0
> END MODULE FOO_MODULE
>
> PROGRAM FOO
> * USE foo_module
> * IMPLICIT NONE
> * REAL(KIND=NP) :: X, Y, Z
> * ! Define Input Values
> * X=2.0_NP
> * Y=3.0_NP
> * ! Print K
> * WRITE(*,*)'BEFORE) K=',K
> * ! Call Subroutine
> * CALL FOO_FUN(X,Y,Z)
> * ! Print K
> * WRITE(*,*)'AFTER) *K=',K
> END PROGRAM FOO
>
> SUBROUTINE FOO_FUN(X,Y,Z)
> * USE foo_module
> * IMPLICIT NONE
> * REAL(KIND=NP), INTENT(IN) *:: X, Y
> * REAL(KIND=NP), INTENT(OUT) :: Z
> * ! Compute Output Z
> * Z=PI*X*Y
> * ! Update K
> * K=K+1
> END SUBROUTINE FOO_FUN
>
> Compile:
> ifort foo_module.f90 foo.f90 -o foo.x
>
> Execution:
> *BEFORE) K= * * * * * 0
> *AFTER) *K= * * * * * 1
>
> So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous.
>
> There is a way to permit to change the variables only explicitly?


I am not certain what you mean.

You might want to look into the PROTECTED attribute.

You could make the module variables PRIVATE, and use
assessor functions and updater subroutines to get and
set their values.

Bob Corbett
Reply With Quote
  #5 (permalink)  
Old 04-24-2012, 09:38 AM
Marco Zannoni
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:
> Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende:
> > Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
> > Here's a simple example:
> >
> > MODULE FOO_MODULE
> > IMPLICIT NONE
> > INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15)
> > REAL(KIND=NP), PARAMETER :: PI=3.14_NP
> > INTEGER :: K=0
> > END MODULE FOO_MODULE
> >
> > PROGRAM FOO
> > USE foo_module
> > IMPLICIT NONE
> > REAL(KIND=NP) :: X, Y, Z
> > ! Define Input Values
> > X=2.0_NP
> > Y=3.0_NP
> > ! Print K
> > WRITE(*,*)'BEFORE) K=',K
> > ! Call Subroutine
> > CALL FOO_FUN(X,Y,Z)
> > ! Print K
> > WRITE(*,*)'AFTER) K=',K
> > END PROGRAM FOO
> >
> > SUBROUTINE FOO_FUN(X,Y,Z)
> > USE foo_module
> > IMPLICIT NONE
> > REAL(KIND=NP), INTENT(IN) :: X, Y
> > REAL(KIND=NP), INTENT(OUT) :: Z
> > ! Compute Output Z
> > Z=PI*X*Y
> > ! Update K
> > K=K+1
> > END SUBROUTINE FOO_FUN
> >
> > Compile:
> > ifort foo_module.f90 foo.f90 -o foo.x
> >
> > Execution:
> > BEFORE) K= 0
> > AFTER) K= 1
> >
> > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous.
> >
> > There is a way to permit to change the variables only explicitly?
> > This problem is related to the SAVE attribute?

>
> If you want to limit the accessibility and use these variables only as a
> means to share information within the module, you can use the PRIVATE
> attribute or statement:
>
> integer, private :: k = 0
>
> Then only routines in the module can access that particular variable k.
> (Routines that use the module, could define an alternative variable called "k"
> or acquire one from a different module, but this particular variable k will
> no longer be visible.)
>
> Regards,
>
> Arjen


Thanks, this was exaclty what I was looking for.
Reply With Quote
  #6 (permalink)  
Old 04-24-2012, 12:32 PM
Wolfgang Kilian
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

On 04/24/2012 11:38 AM, Marco Zannoni wrote:
> Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:
>> Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende:
>>> Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
>>> Here's a simple example:

[...]
>> If you want to limit the accessibility and use these variables only as a
>> means to share information within the module, you can use the PRIVATE
>> attribute or statement:
>>
>> integer, private :: k = 0
>>
>> Then only routines in the module can access that particular variable k.
>> (Routines that use the module, could define an alternative variable called "k"
>> or acquire one from a different module, but this particular variable k will
>> no longer be visible.)
>>
>> Regards,
>>
>> Arjen

>
> Thanks, this was exaclty what I was looking for.


You may consider setting the _default_ accessibility of all module
entities to private, and mark only those entities as public that you
really need outside the module.

My personal preference is to avoid module variables altogether where
possible. When they are necessary, give them verbose names to minimize
the impact of missing declarations and typos.

-- Wolfgang

--
E-mail: firstnameinitial.lastname@domain.de
Domain: yahoo
Reply With Quote
  #7 (permalink)  
Old 04-24-2012, 03:00 PM
Richard Maine
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

Wolfgang Kilian <seesig@domain.invalid> wrote:

> On 04/24/2012 11:38 AM, Marco Zannoni wrote:
> > Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:


> >> If you want to limit the accessibility and use these variables only as a
> >> means to share information within the module, you can use the PRIVATE
> >> attribute or statement:
> >>
> >> integer, private :: k = 0


> > Thanks, this was exaclty what I was looking for.

>
> You may consider setting the _default_ accessibility of all module
> entities to private, and mark only those entities as public that you
> really need outside the module.


That's what I recommend. To do so, just use the PRIVATE statement with
no particular entities specified, as in just

private

This goes right by the "implicit none" (which I do see that the OP
uses). With modules, "implicit none" becomes even more important because
without it you can't easily tell whether a variable is implicitly
declared or accessed from a module.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Reply With Quote
  #8 (permalink)  
Old 04-24-2012, 04:43 PM
Ron Shepard
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

In article <1kj1pyw.s6yvn6r10s8gN%nospam@see.signature>,
nospam@see.signature (Richard Maine) wrote:

> Wolfgang Kilian <seesig@domain.invalid> wrote:
>
> > On 04/24/2012 11:38 AM, Marco Zannoni wrote:
> > > Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:

>
> > >> If you want to limit the accessibility and use these variables only as a
> > >> means to share information within the module, you can use the PRIVATE
> > >> attribute or statement:
> > >>
> > >> integer, private :: k = 0

>
> > > Thanks, this was exaclty what I was looking for.

> >
> > You may consider setting the _default_ accessibility of all module
> > entities to private, and mark only those entities as public that you
> > really need outside the module.

>
> That's what I recommend. To do so, just use the PRIVATE statement with
> no particular entities specified, as in just
>
> private
>
> This goes right by the "implicit none" (which I do see that the OP
> uses). With modules, "implicit none" becomes even more important because
> without it you can't easily tell whether a variable is implicitly
> declared or accessed from a module.


There are two aspects of the original question. One if if you are
writing a module that will be used by other programmers, and you
want to protect the module variables that are intended to be shared
only within the module. I think the above comments address mostly
this situation. You declare some or all of the module variables to
be private, and except for some trickery, those variables will not
be visible or accessible directly outside of the module. The
"trickery" involves pointers or using those private variables as
actual arguments to other subroutines (which then can modify them,
perhaps intentionally or perhaps by mistake).

The other situation is when you are on the other side and you are
USEing a module (written by you or by someone else). If you don't
want to modify any of the module variables by mistake, and you want
the compiler to help you avoid doing that, then you can develop the
programming habit of always using the ONLY clause with the USE
statements. This is useful in several ways. In addition to the
unintentional modification problems this avoids, it also documents
in the USEing subroutine exactly where particular variables live (or
at least how you are accessing them, which is not quite the same
thing, but you probably see the difference). Consider the following

use mod1
use mod2
use mod3
implicit none
...

k = k + 1
...

You know that "k" must be in one of those modules because otherwise
the compiler would complain (due to the implicit none and the lack
of a local declaration). But you don't know which one, and to track
it down you would need to search through the source to all those
modules (or worse, dig down several levels of modules to find it,
with the breadth of your search increasing exponentially with the
depth). If instead, you had written

use mod1, only: a, b, c
use mod2, only: i, j, k
use mod3, only: x, y, z
...

then it would be clear at a glance how "k" became accessible in your
code. If you then look in module mod2, and if it also uses ONLY
clauses like this, then you could quickly track down exactly where
that variable was declared. You could also search your code for
other "use mod2" statements to see where else that variable has been
made accessible.

As nice as all this sounds, one complaint I have is that it is
simply a programming convention. If you slip up somewhere and USE
mod2 without the only clause, then you are back with all of the
original problems. You just shot yourself in the foot, and you
might not know about it until some multiday debugging excursion to
track down some problem with a variable being modified. Currently,
there is no way to enforce the requirement that ONLY clauses must be
used (say, IMPLICIT ONLY NONE or REQUIRE ONLY or some similar
declaration) so that the compiler can help you enforce this. You
are just on your own to try to enforce your chosen programming
convention with little or no additional help available from the
compiler.

$.02 -Ron Shepard
Reply With Quote
  #9 (permalink)  
Old 04-25-2012, 12:45 AM
michaelmetcalf@compuserve.com
Guest
 
Posts: n/a
Default Re: Confusion with variables in modules

On Tuesday, April 24, 2012 6:38:47 PM UTC+9, Marco Zannoni wrote:
> Il giorno martedì 24 aprile 2012 10:09:08 UTC+2, Arjen Markus ha scritto:
> > Op dinsdag 24 april 2012 09:23:44 UTC+2 schreef Marco Zannoni het volgende:
> > > Hi, I'm confused about the behavior of the variables defined in a module, in particular regarding the possibility to change them.
> > > Here's a simple example:
> > >
> > > MODULE FOO_MODULE
> > > IMPLICIT NONE
> > > INTEGER, PARAMETER :: NP = SELECTED_REAL_KIND(15)
> > > REAL(KIND=NP), PARAMETER :: PI=3.14_NP
> > > INTEGER :: K=0
> > > END MODULE FOO_MODULE
> > >
> > > PROGRAM FOO
> > > USE foo_module
> > > IMPLICIT NONE
> > > REAL(KIND=NP) :: X, Y, Z
> > > ! Define Input Values
> > > X=2.0_NP
> > > Y=3.0_NP
> > > ! Print K
> > > WRITE(*,*)'BEFORE) K=',K
> > > ! Call Subroutine
> > > CALL FOO_FUN(X,Y,Z)
> > > ! Print K
> > > WRITE(*,*)'AFTER) K=',K
> > > END PROGRAM FOO
> > >
> > > SUBROUTINE FOO_FUN(X,Y,Z)
> > > USE foo_module
> > > IMPLICIT NONE
> > > REAL(KIND=NP), INTENT(IN) :: X, Y
> > > REAL(KIND=NP), INTENT(OUT) :: Z
> > > ! Compute Output Z
> > > Z=PI*X*Y
> > > ! Update K
> > > K=K+1
> > > END SUBROUTINE FOO_FUN
> > >
> > > Compile:
> > > ifort foo_module.f90 foo.f90 -o foo.x
> > >
> > > Execution:
> > > BEFORE) K= 0
> > > AFTER) K= 1
> > >
> > > So, if I understand correctly, every subroutine that USE a module, can change the value of the variables defined into it. This can be useful, but also dangerous.
> > >
> > > There is a way to permit to change the variables only explicitly?
> > > This problem is related to the SAVE attribute?

> >
> > If you want to limit the accessibility and use these variables only as a
> > means to share information within the module, you can use the PRIVATE
> > attribute or statement:
> >
> > integer, private :: k = 0
> >
> > Then only routines in the module can access that particular variable k.
> > (Routines that use the module, could define an alternative variable called "k"
> > or acquire one from a different module, but this particular variable k will
> > no longer be visible.)
> >
> > Regards,
> >
> > Arjen

>
> Thanks, this was exaclty what I was looking for.


Also, since no-one else mentioned it, while you're writing such code pleasenote that you can avoid other potential problems by making FOO_FUN into a module procedure or into an internal procedure. That will prevent you from making undetected and hard-to-debug errors with prcedure interfaces.

Regards,

Mike Metcalf
Reply With Quote
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 10:00 AM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.