From: Richard E Maine on 9 Mar 2006 11:23 Catherine Rees Lay <spamtrap(a)polyhedron.com> wrote: > One thing which really, really bugs me about USE statements is ONLY. .... > I much prefer code written so that > you'd have a bare USE PRINTING, and then you don't have to worry about > changing it to call another printing routine which was there all along. I tend to agree with Catherine here. Anyway, that's the way I actually code, abstract arguments aside. And no, generics don't solve it; they are only a small part. While I see the arguments for being able to explicitly see all the imported names, I don't end up actually doing that. I think Catherine has hit on my justification and explained it better than I have. Or maybe I'm just looking for excuses other than laziness on my part. :-) My USE statemens are more about bringing in functionality than individual names. The functionality can involve multiple names, and in ways other than those handled by generics. For example, I have a module named th_read (for reading time history files). It brings in procedures to open, close, position, inquire about properties, request signals, and read a time frame. It also has a derived type for a "file handle", and some named constants for status return values. No way I'm going to do something like list just the particular status return values I happen to reference in a particular scope so that I have to check whether I've already imported that one every time I reference one of them. I could possibly see arguments for having a template USE that specified everything available from that module. PITA to type in everywhere, but maybe I could just cut&paste. THat way, I'd at least have the explicit list of names visible. But I'd still have a maintenance issue if I added something to the public things in the module. I'd then need to go back and change every USE statement, unless I wanted the ONLYs to get out of sync with what was actually available. I appreciate the theoretical arguments for why people should use ONLY for everything, but I don't do it myself and I think that is telling about something (even if only about me). I've never actually had a name conflict as a result of my sytle in this. Of course, that might be because 1. I always use IMPLICIT NONE. I would agree that having an unnadorned USE without IMPLICIT NONE is a mess. You can't tell whether undeclared things are implicitly typed, used from a module, or just a bug/typo. With IMPLICIT NONE, you eliminate the implicit typing possibility. They might still be a bug/typo, but the compiler will tell you that anyway. I like IMPLICIT NONE anyway, but I think it doubly important when you use modules (and it is worse still when you thro host association into the mix). 2. The names I export from modules tend to be long enough to at least give a hint as to where they came from. Not ludicrously long, but enough that they will be unique in practice and also self-document where they were from. Generally, I make names more explicit when they get used non-locally. I've been burned by failing to do that in the long past (see my signature). For example, long ago, in 6-character f77 days, I had my own functions named fread and fseek. That was also prior to my exposure to C and Unix. Those later turned out to be "unfortunate" names for externals, particularly on HP systems that didn't do the now-common underscore convention for external name mangling. I am aware that some (even most?) people use and recommend different styles from the one I use in this area. I'm not trying to argue for this as "the one and only reasonable style". More like - I'm trying to defend it as not an entirely unreasonable choice. -- Richard Maine | Good judgment comes from experience; email: my first.last at org.domain| experience comes from bad judgment. org: nasa, domain: gov | -- Mark Twain
From: Paul Van Delst on 9 Mar 2006 11:29 Richard E Maine wrote: > Arjen Markus <arjen.markus(a)wldelft.nl> wrote: > > >>A bare PRIVATE keyword makes everything private, unless you explicitly >>declare it PUBLIC, this is even true for things imported via USE (or at >>least that is the effect that I have seen with a number of compilers): > > > Ah... sort of. First, the standard specifies this - not just particular > compilers. But second, there is a very subtle quirk in the exact wording > of the standard. The quirk is intentional; it matters. > > The PUBLIC keyword makes things public. That part is ok. You might think > that the PRIVATE keyword would make things private, but that's not > actually what the standard says. Instead, it has a strangely double > negative form. I can cite the exact words (or darned close) even without > opening the standard, because thi was once the subject of carefull study > in an f90 interp a decade ago. > > The PRIVATE attribute for an entity specifies that the entity "is not a > public entity of the module". Why the negative form? Part of the reason > is that "of the module" phrase and it relates to things imported via > USE. If some identifier was imported via USE, then that is not a private > identifier. If it were, it couldn't have been imported by USE. Nothing > that the importing module does can change the fact that the identifier > was public in its original module of definition. All that PRIVATE does > for such an imported identifier is say that it won't be re-exported (my > term) from this module. But that doesn't mean it is private to this > module - it can't very well be because it isn't even "owned" by this > module. > > I personally think that the terminology is unfortunate in that public > indeed means public, but private doesn't really mean private. Instead, > private means something closer to "don't export from here". > > In f90 and f95 it mattered because there were some "funny" restrictions > relating to private things, so you needed to know what things those > restrictions applied to. I think all those "funny" restrictions are gone > in f2003, so the picky distinctions about whether something is or is not > "really" private might not matter any more there. But, despite this subtlety, isn't the end result what people would commonly (intuitively?) expect? Public means that entities are "visible from" a module if that module is USEd. Private means that entities are NOT "visible from" a module if that module is USEd. ? cheers, paulv -- Paul van Delst CIMSS @ NOAA/NCEP/EMC
From: Keith Refson on 9 Mar 2006 11:30 Richard E Maine wrote: > Arjen Markus <arjen.markus(a)wldelft.nl> wrote: > >> A bare PRIVATE keyword makes everything private, unless you explicitly >> declare it PUBLIC, this is even true for things imported via USE (or at >> least that is the effect that I have seen with a number of compilers): > > Ah... sort of. First, the standard specifies this - not just particular > compilers. But second, there is a very subtle quirk in the exact wording > of the standard. The quirk is intentional; it matters. [ explanation snipped] In that case I wonder what the standard says about the following situation? module A private integer, public :: AI=4 end module A module B use A private end module B program C use B implicit none write(*,*) AI end program C Specifically, does the public attribute on the declaration of A::AI mean that B::AI is explicitly public, or private by default? Keith Refson -- Dr Keith Refson, Building R3 Rutherford Appleton Laboratory Chilton Didcot kr AT Oxfordshire OX11 0QX isise D@T rl D.T ac D?T uk
From: Dan Nagle on 9 Mar 2006 11:42 Hello, Catherine Rees Lay wrote: <snip> > Yes, in that case, it would work. > > How about a graphics module? Draw line, draw circle, draw polygon... You > might be able to twist it to have one generic draw shape routine, but > I'd think it much clearer to have draw line with two endpoints, draw > circle with a centre and a radius, draw polygon with a number of corners > and an array of coordinates, and so on. And I really, really hate having > to modify what I consider to be a description of the code's underlying > structure (the USE statement) just because my client has decided that > the caterpillar-drawing routine which uses the circle function should > also do legs. <snip> Yes, I don't use only clauses with something like winteracter. It's too big, and I trust them not to use "obvious" names. I don't have routines of my own whose names start with IGR... or IPG... But with my own, more modest efforts, yes I find only to be useful. -- Cheers! Dan Nagle Purple Sage Computing Solutions, Inc.
From: Richard E Maine on 9 Mar 2006 12:56
Keith Refson <K.Refson(a)rl.ac.uk> wrote: > In that case I wonder what the standard says about the following situation? > > module A > private > integer, public :: AI=4 > end module A > > module B > use A > private > end module B > > program C > use B > > implicit none > > write(*,*) AI > end program C > > Specifically, does the public attribute on the declaration of A::AI > mean that B::AI is explicitly public, or private by default? This doesn't quite illustrate the same issue, because you aren't doing any of the things that expose the distinction. It is related, but this isn't the crux of the matter. See my other followup to Paul (which I haven't written yet, but intend to). First, module A. AI is a public entity of module A. That's because it is explicitly declared to be public. The explicit declaration overrides the default for that module. The PRIVATE statement in module A has no effect on anything here. Reread that last sentence - it is important. All that such a PRIVATE statement means is that entities whose accessibility isn't explicitly declared in A get the PRIVATE attribute. There aren't any such entities, so it doesn't matter. And once an entity has the public or private attribute, it doesn't matter whether it got it that way by explicit declaration or by default. Now module B. It USEs A and "imports" AI from A. The PRIVATE statement here does apply to AI because the accessibility of AI from this module isn't explicitly specified eslewhere in the module. The accessibility of AI from module A is specified in module A, but accesssibility is one of the *VERY* few attributes that can be different in different scoping units for the same entity. (VOLATILE is another such attribute, if I recall correctly). So AI is "not a public entity of the module" for module B. So the program is invalid, as AI isn't accessible via B. AI is public, but you have to do a "USE A" to access it. -- Richard Maine | Good judgment comes from experience; email: my first.last at org.domain| experience comes from bad judgment. org: nasa, domain: gov | -- Mark Twain |