|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Keith Waters
Joined: 07 Aug 2007 Posts: 29 Location: London or Somerset, UK
|
Posted: Mon Aug 20, 2007 4:06 pm Post subject: PRIVATE not implemented properly? |
|
|
In this program, Module_1 uses a couple of entities (a function and an integer) from Module_2. Module_1 then specifies that the function, M2_Val, will be made PUBLIC. The blank PRIVATE statement ensures that all other entities will be hidden, which in this case means the integer, m2. At least, that is my understanding of the blank PRIVATE statement.
Code: | C DEMO.FOR
PROGRAM DEMO
USE Module_1
m2 = 6
PRINT *, 'm2 = ', m2
PRINT *, 'M2_Val = ', M2_Val()
END
! --------------------------------------------------------------
! MODULE_1.F90
MODULE Module_1
USE Module_2, ONLY: M2_Val, &
m2
PRIVATE
PUBLIC :: M2_Val
CONTAINS
END MODULE
! --------------------------------------------------------------
! MODULE_2.F90
MODULE Module_2
PRIVATE
INTEGER(KIND=SELECTED_INT_KIND(9)) :: m2 = 0
PUBLIC M2_Val, &
m2
CONTAINS
FUNCTION M2_Val ()
INTEGER(KIND=SELECTED_INT_KIND(9)) :: M2_Val
M2_Val = m2
END FUNCTION
END MODULE
|
The main program USEes Module_1 and attempts to access the integer, m2, directly. The program output is:
m2 = 6
M2_Val = 6
This output demonstrates that the main program has, indeed, been able to access m2 directly. The compiler gives no error message for this. I believe it should.
I’m using the compiler options, /ISO /IMPLICIT_NONE /NO_SCALAR_TO_ARRAY /RESTRICT_SYNTAX /CHECKMATE, and linking with SLINK.
Keith |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Tue Sep 04, 2007 5:21 pm Post subject: |
|
|
This is one of those vague areas where it is difficult to know what the Fortran standard demands. Another popular compiler produces the same results as FTN95 and makes m2 public because is it declared as PUBLIC when it is defined in Module_2.
OK it is used through a sort of inheritance via Module_1 where it is marked as PRIVATE but this is Fortran not C++.
Maybe the compiler should issue a warning when m2 is marked as PRIVATE in Module_1 but this is a minor omission.
At the moment I am assuming that this is not a bug in FTN95. |
|
Back to top |
|
|
Keith Waters
Joined: 07 Aug 2007 Posts: 29 Location: London or Somerset, UK
|
Posted: Thu Oct 04, 2007 3:35 pm Post subject: |
|
|
At the very least this means that the FTN95 help is wrong.
From the FTN90 Help in the section entitled “Modules”, subsection “The PRIVATE and PUBLIC statements”,
Quote: “A PRIVATE statement without a list makes all variables PRIVATE by default.”.
This is wrong and should read, “A PRIVATE statement without a list makes all variables PRIVATE by default unless they have been imported with the USE statement from another module.”.
An alternative wording might be, “A PRIVATE statement without a list makes all variables declared in the module PRIVATE by default. Variables imported from another module with the USE statement remain PUBLIC unless explicitly declared PRIVATE”.
I must say I still find this a complicated interpretation on the part of the FTN95 compiler designers. In my opinion the sensible decision would have been to have the following simple statement apply to all entities in the module, irrespective of whether they have been declared in the module or have been imported from another module.
“A PRIVATE statement without a list makes all data items and procedures PRIVATE by default”
I don’t know if any textbooks on the subject of programming with Fortran 90/95 go along with your interpretation but the one I have, “Fortran 90/95 for Scientists and Engineers” by Stephen J. Chapman, seems to be in the spirit of the interpretation I prefer.
Quote:
"Good Programming Practice
It is good programming practice to hide any module data items or procedures that do not need to be directly accessed by external program units. The best way to hide data items and procedures is to include a PRIVATE statement in each module and then list the specific items that you wish to make visible in a separate PUBLIC statement.” |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Thu Oct 04, 2007 4:33 pm Post subject: |
|
|
Fair enough but the point is a very fine one and one that the standards committe probably didn't even contemplate never mind the poor compiler writers.
Fortran modules are not like C++ classes.
Suppose module A contains a PUBLIC variable x and module B accesses x but makes x PRIVATE from users of B. Module A has to be made available to users of either A or B. So how is the variable x protected from external use? Users can access it directly from module A.
If you want a variable to be private then you should design your modules so that it is defined as private in the base module. |
|
Back to top |
|
|
Keith Waters
Joined: 07 Aug 2007 Posts: 29 Location: London or Somerset, UK
|
Posted: Thu Oct 04, 2007 10:19 pm Post subject: |
|
|
I do take your point about the standards committee probably not even contemplating this.
I’ve never programmed in C++ although I am familiar with object-oriented concepts. And it must be said that the FTN95 help (section “Modules”) does make passing reference.
Quote: “A MODULE can also contain the definition of user-defined types together with the definition of procedures that are common to a number of program units. Some of these procedures may be used to create user-defined operators. In this respect, a MODULE can be designed to be "object oriented".”
In your example modules A and B, I take your point that module A has to be made available to users of A or B, otherwise they cannot compile their program. However, that doesn’t mean they are forced to put a “USE A” statement in their program if they only need to USE module B.
I agree with you that users can access variable x directly from module A. However, with my interpretation of the PRIVATE statement, they have to explicitly state they are going to USE A. I think that’s only right and proper and, to my mind, does provide some protection of x. With the FTN95 interpretation they can access it without doing USE A and I think there is the increased possibility they could inadvertently corrupt it.
Quote: | If you want a variable to be private then you should design your modules so that it is defined as private in the base module. |
Yes, but that is not quite what we are talking about. We are talking about entities that need to be exported to a higher-level module but no further.
Perhaps I should put all this into some context. I’ve written some, what I regard as, “low level” modules that implement a Stack, a Dictionary, a Buffer, and a few other esoteric things. Then I have “intermediate level” modules implementing a Document and a Notation. These modules are then used in a “top level” module (let’s call it module Top), which is the only module my users will ever need to reference in a USE statement.
So, I tell my users to place the statement, “USE Top”, in every program unit that needs to use my work. I don’t want them to be able to access the low level Stack, Dictionary, etc. stuff so to get round FTN95’s insistence on ignoring the blank PRIVATE statement for imported entities, I explicitly declare these entities as PRIVATE in my intermediate and top level modules. Of course, they could still access these entities after writing USE Stack, for example, but that would be going against my advice – so my back is covered.
But hang on a minute. These low level Stack, Dictionary, etc modules are generic enough that I might want to make use of them in other projects. When I do, I am again unlikely to want these low level esoteric entities to be propagated up any hierarchy of modules. So whenever I use one of these low level modules I must place the following statement in the using module.
Code: | PRIVATE :: esoteric_entity_1, &
esoteric_entity_2, &
….
esoteric_entity_n |
I think that is a pain but, more importantly, I think it compromises the ease and safety of the module usage.
I suppose this could all be argued and discussed till the cows come home. Perhaps you are right in suggesting that I am thinking in a non-Fortran manner. If that is the case, then I must say I am disappointed in the direction Fortran is taking the Module concept. However, just as you flagged the existence of another compiler that does it the FTN95 way, I can say that I am using a very well known compiler that does it my way.
Regards
Keith |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Fri Oct 05, 2007 7:49 am Post subject: |
|
|
OK, you will naturally use the compiler that best suits your needs. |
|
Back to top |
|
|
wws
Joined: 25 Oct 2007 Posts: 7 Location: California
|
Posted: Thu Oct 25, 2007 6:54 pm Post subject: |
|
|
Unfortunately, FTN95 has implemented this wrongly. The PRIVATE in his Module_1 should prevent m2 from 'leaking through' to the USEr of Module_1. Unless, of course, it is explicitly made public - as is the case of m2_val.
With the /IMPLICIT_NONE option specified, the main program should have given an error message on the use of m2. |
|
Back to top |
|
|
tomo.bbe
Joined: 26 Feb 2008 Posts: 3
|
Posted: Fri Mar 14, 2008 3:58 pm Post subject: |
|
|
I think the following code is a similar if not the same issue but with derived type components. The following compiles correctly with FTN95 and alters the private attribute in type (m1). Is this a misinterpretation on my part or an ambiguity in the standards?
Code: |
module mod1
! Module One
! Simple type (m1) with private contents
! My understanding is that attribute "a" can not be altered by anything
! as there are no methods in this module to do so.
type m1
private
integer :: a = 1
end type
end module
module mod2
! Module Two
! Type (m2) descends m1
! As the contents of m1 are private routines in mod2 should not be able to alter
! the contents of this attribute on (m2) types.
use mod1
type m2
private
type (m1) :: m
end type
contains
subroutine printm(self)
! Simple routine to test that the private condition is violated
! for type (m1)
type (m2) :: self
! The calling programme cannot do this so why can this module?
print *,self%m
! Sure self%m%a is a private attribute of self%m and should only
! be alterable for module mod1
self%m%a = 2
print *,self
end subroutine
end module
program private
! Programme to test the above modules.
use mod2
! My two types
type (m2) :: two
type (m1) :: one
call printm(two)
! All of the follwoing commands correctly raise errors in the compiler.
!one%a = 2
!two%one%a = 3
!print *,one
!print *,two
!print *,two%two
!print *,two%two%a
end program
|
|
|
Back to top |
|
|
Keith Waters
Joined: 07 Aug 2007 Posts: 29 Location: London or Somerset, UK
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Mon Mar 17, 2008 8:39 am Post subject: |
|
|
Thanks.
This bug has already been fixed in the current release (5.20). |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|