FUNCTION MEAN_OF_2 (V1, V2) RESULT(MEAN)
IMPLICIT NONE
! declare arguments
REAL, INTENT(IN) :: V1, V2
! declare function result
REAL :: MEAN
! begin MEAN_OF_2
MEAN = (V1 + V2) / 2.0
RETURN
END FUNCTION MEAN_OF_2
Strictly speaking, we don't need the RESULT() specification for
this function, and could just write:
FUNCTION MEAN_OF_2 (V1, V2)
IMPLICIT NONE
REAL, INTENT(IN) :: V1, V2
REAL :: MEAN_OF_2
! begin MEAN_OF_2
MEAN_OF_2 = (V1 + V2) / 2.0
RETURN
END FUNCTION MEAN_OF_2
Which is preferable? (I have been teaching my students to consistently
use the RESULT() specification for all F90 functions, and am wondering
if I am causing irreparable brain damage.)
My theory (and this point, that's all it is) is that it is "clearer" to
assign a function result to a "result variable", and not to assign a
function result to a function name, since conceptually a function name
is _not_ a variable, and yet in the RESULT()-less form of the function
above, we are assigning to the name of the function as if it _were_ a
variable.
I have done Fortran programming for a while (Fortran II, IV, 77), so
I am familiar with how traditional Fortran does things. My instinct at
the moment is that when F90 gives us a new and "clearer" way
to express our processes, we might as well use it...!
But: my reasoning could well be mistaken. What do you c.l.f. readers
think? Should we relegate the use of RESULT() only to recursive and
pointer-valued functions?
Thanks in advance.
--
Louis Glassy (l...@cs.montana.edu)
For the reasons you state, it is indeed a better method to adopt, and in the F
subset the result clause is actually mandatory - an F student doesn't even
know that there is another way to program a function.
Regards,
Mike Metcalf
In F90, do you think it is preferable to use the RESULT() specification
for functions which don't require it?
Yes. Generally I'm in favor of writing code to express more of what
the programmer intends to express, and less of what he doesn't.
I can't imagine, offhand, why a programmer would _intend_ to write
a reference to a name that expresses the concept "either the
containing function _or_ its return value", which is what the F77
approach requires. F90 allows the programmer to always distinguish
between "the containing function" vs. "the return value" by selecting
a different name for the latter.
Another advantage of this sort of distinction is separation of internal
vs. external names.
Generally, a language such as Fortran or C (especially ANSI C and Fortran
90, which offer prototypes/interfaces) should make it easy, and safe
to change the _external_ interface of a module/procedure while not
changing its _internals_, and vice versa.
Consistent use of RESULT() realizes this, at least partially, for F90
programs, because once you have
FUNCTION FOO ... RESULT(BAR)
you can change the internals of FOO such that the names are more descriptive
(including BAR) without affecting the external interface (the name FOO itself,
in this case). And/or you can decide to give the function a more descriptive
external name, or give it a name that fits into local (program/project/
organization) coding conventions, again by changing only the "FOO" name and
the function's callers, without having to change all the code that
manipulates BAR.
I'll admit that much of what goes into my appreciation for this difference
is the difficulty many programmers still have changing names of things
throughout a program unit, a module, or a program in Fortran, C, etc. Even
today, when most programmers have access to tools allowing them to do this
with a fair degree of reliability, the fact is that the access is not
sufficient to give perhaps even a majority of programmers the sufficiently
warm, cuddly feeling that they _know_ how to use those tools and _will_ use
them correctly and safely.
But, a simple technical reason one _generally_ wants to be able to keep
internal names the same while changing external names, and vice versa, is
that there exist features (such as Fortran's NAMELIST) that effectively
"publish" internal names to a scope well beyond the program unit itself --
e.g. external data bases, some of which are on tape.
Now, I'll admit that in NAMELIST's case, and frankly in any case where a
language offers a similar facility, it amounts to a language deficiency that
a straightforward explicit translation of externally visible to internally
visible names cannot be safely specified. E.g. Fortran's NAMELIST could
allow something like
NAMELIST /X => "Y"/ A => "VALUE1", B => "VALUE2"
as an alternative to changing
NAMELIST /X/ A, B
to
NAMELIST /Y/ VALUE1, VALUE2
(along with all further internal references to those names), and tools
for that language should even provide automated instantiation of the
interface once it is used in production code so that the interface may
be easily "frozen" in place (e.g. automatic conversion of
NAMELIST /X/ A, B
to
! This NAMELIST has been used to generate production data files
! as of 2015-02-30 23:59:60, therefore, its external interface
! must not change from NAMELIST /"X"/ "A", "B":
!
NAMELIST /X => "X"/ A => "A", B => "B"
(except the commentary will probably be in Spanish by then ;-).
Nevertheless, the above is just another example of why RESULT() should
probably be regularly used to start the internal/external distinction
off on the right foot. That is, even if NAMELIST had the above
facility, that'd be more persuasive evidence (than this post of mine ;-)
that the external/internal distinction is worth making, on a regular
basis, which would argue for using RESULT() regularly.
Another seeming facet to this is that NAMELIST doesn't allow dummy
arguments and, I am guessing offhand, disallows return values as
well. I disagree this is a reason to wave off NAMELIST and perhaps the
whole reason to use RESULT() regularly, simply because, at least in
theory, NAMELIST _can_ be extended to support return values and
dummy arguments, so the principle stands at a meta-language level.
Maybe the simplest reason of all, though, is that while scalar-valued
functions are lexically easy for humans (and compilers) to distinguish
between their invocations and references to their return value, this is
not so true for array-valued or CHARACTER functions.
E.g., given:
FUNCTION FOO()
it's easy to distinguish
...FOO()...
from
...FOO...
But, given:
CHARACTER*80 FOO(J)
it's impossible to tell what
...FOO(I+LEN(A//B)-K**2...
refers to -- the crucial parts are intentionally left off, because people
[and computers] shouldn't have to read that far to tell whether the
"FOO(" is a function reference or a variable reference, a problem Fortran
already has in general but should be reduced, in practice, where it is
practical to do so.
--
"Practice random senselessness and act kind of beautiful."
James Craig Burley, Software Craftsperson bur...@gnu.ai.mit.edu
In your program that calls the function, you use its name, so why use a
different name inside the function when you don't have to? If you were writing
your algorithm in mathematical notation, you might say:
y = f(x)
where
f(x) = x + ...
You could replace the last line by:
f(x) = result
where
result = x + ...
but why bother?
The result clause is only there as a convenience for the compiler so that it
can compile recursive functions without getting confused by having the same
name play two different roles.
--
Ronald Sverdlove Computational Science Research
r...@sarnoff.com David Sarnoff Research Center
Tel. 609-734-2517 CN 5300
FAX 609-734-2662 Princeton, NJ 08543-5300
Actually, I find the use of RESULT() to be less clear. I opposed
its introduction into the language. Of course, if backward
compatibility were not an issue, using the RETURN <expression>
form that all other languages use would be preferable to either
using the function name or the RESULT clause.