From: Richard E Maine on
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
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
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
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
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