Home > Archive > Fortran > March 2008 > better way to name optional argument
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
better way to name optional argument
|
|
|
| Hi
I'd like to ask how you name the variable of optional argument?
For an existent subroutine, I'd like to add an optional argument to do
some test:
1a/ integer :: iTEST
if(present(iTEST))then
print *,iTEST,'do some test!'
else
print *,iTEST,'no need to do some test!'
end if
1b/ or
if(iTEST==1)then
print *,iTEST,'do some test!'
else
print *,iTEST,'no need to do some test!'
end if
2a/ logical :: lTEST
if(present(lTEST))then
print *,lTEST,'do some test!'
else
print *,lTEST,'no need to do some test!'
end if
2b/ or
if((lTEST))then
print *,lTEST,'do some test!'
else
print *,lTEST,'no need to do some test!'
end if
I don't know which one is a meaningful one.
It goes much complicated when there are also optional arguments to be
set when optional argument TEST is a must. I'd like to set two
parameters: ipar1,ipar2.
I am also how is the best way to set the if ... else ....end
if.
Any suggested example would be very much appreciated.
Mike
| |
| octaedro 2008-03-08, 4:32 am |
| On Mar 7, 8:58=A0pm, Mike <Sulfate...@gmail.com> wrote:
> Hi
>
> I'd like to ask how you name the variable of optional argument?
> For an existent subroutine, I'd like to add an optional argument to do
> some test:
> 1a/ integer :: iTEST
> =A0 =A0 =A0 =A0 if(present(iTEST))then
> =A0 =A0 =A0 =A0 =A0 print *,iTEST,'do some test!'
> =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 print *,iTEST,'no need to do some test!'
> =A0 =A0 =A0 =A0 end if
> 1b/ or
> =A0 =A0 =A0 =A0 if(iTEST=3D=3D1)then
> =A0 =A0 =A0 =A0 =A0 print *,iTEST,'do some test!'
> =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 print *,iTEST,'no need to do some test!'
> =A0 =A0 =A0 =A0 end if
>
> 2a/ logical :: lTEST
> =A0 =A0 =A0 =A0 if(present(lTEST))then
> =A0 =A0 =A0 =A0 =A0 print *,lTEST,'do some test!'
> =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 print *,lTEST,'no need to do some test!'
> =A0 =A0 =A0 =A0 end if
> 2b/ or
> =A0 =A0 =A0 =A0 if((lTEST))then
> =A0 =A0 =A0 =A0 =A0 print *,lTEST,'do some test!'
> =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 print *,lTEST,'no need to do some test!'
> =A0 =A0 =A0 =A0 end if
>
> I don't know which one is a meaningful one.
>
> It goes much complicated when there are also optional arguments to be
> set when optional argument TEST is a must. =A0I'd like to set two
> parameters: ipar1,ipar2.
> I am also how is the best way to set the if ... else ....end
> if.
>
> Any suggested example would be very much appreciated.
>
> Mike
Take into account that you also have the CASE cocnstruct that
sometimes is more suuitable than using IF. Additionally you can put
some subroutines that do the same thing but with a varying number of
arguments into a module and use an INTERFACE to associate them with a
given name. I don't know if this short comment is of much help
| |
| Ron Shepard 2008-03-08, 10:23 pm |
| In article
<076f994e-66b4-4193-8929-6ef4577a9610@s37g2000prg.googlegroups.com>,
Mike <SulfateIon@gmail.com> wrote:
> I'd like to ask how you name the variable of optional argument?
> For an existent subroutine, I'd like to add an optional argument to do
> some test:
> 1a/ integer :: iTEST
> if(present(iTEST))then
> print *,iTEST,'do some test!'
> else
> print *,iTEST,'no need to do some test!'
> end if
I cannot answer your question whether it should be an integer or a
logical value. That depends on how you want the test to work.
But I wanted to point out that if the optional argument is not
present, then you cannot reference it in any way (except the
present() test). You cannot use it in an expression, and you cannot
print it (as above). You can use it as an actual argument provided
the corresponding dummy argument is also optional, and in that case
the present() status gets propagated down in the way that you would
expect.
As far as the actual name of the argument, that matters a little
more for optional arguments because they are more often referenced
in the calling sequence with keywords rather than by position. In
this case the keyword should have some meaningful name, hopefully
one that reveals the function of the argument and is easy to
remember and to spell.
$.02 -Ron Shepard
| |
| Gary Scott 2008-03-08, 10:23 pm |
| Mike wrote:
> Hi
>
> I'd like to ask how you name the variable of optional argument?
> For an existent subroutine, I'd like to add an optional argument to do
> some test:
> 1a/ integer :: iTEST
> if(present(iTEST))then
> print *,iTEST,'do some test!'
> else
> print *,iTEST,'no need to do some test!'
> end if
> 1b/ or
> if(iTEST==1)then
> print *,iTEST,'do some test!'
> else
> print *,iTEST,'no need to do some test!'
> end if
>
> 2a/ logical :: lTEST
> if(present(lTEST))then
> print *,lTEST,'do some test!'
> else
> print *,lTEST,'no need to do some test!'
> end if
> 2b/ or
> if((lTEST))then
> print *,lTEST,'do some test!'
> else
> print *,lTEST,'no need to do some test!'
> end if
>
> I don't know which one is a meaningful one.
>
> It goes much complicated when there are also optional arguments to be
> set when optional argument TEST is a must. I'd like to set two
> parameters: ipar1,ipar2.
> I am also how is the best way to set the if ... else ....end
> if.
>
> Any suggested example would be very much appreciated.
>
> Mike
Sometimes, the use of optional arguments isn't the best design. A more
positive approach might be (depending on what you're really trying to
do) to include a "processing type" (or "function code") argument.
Optional arguments are more often useful for items which have a default
value that works in most cases, but you might want to change it on rare
occasion, like an API call to initiate an MDI window that defaults to
cover its entire child area but you might optionally want it to be
minimized.
--
Gary Scott
mailto:garylscott@sbcglobal dot net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| Paul van Delst 2008-03-10, 7:52 pm |
| Mike wrote:
> Hi
>
> I'd like to ask how you name the variable of optional argument?
> For an existent subroutine, I'd like to add an optional argument to do
> some test:
> 1a/ integer :: iTEST
> if(present(iTEST))then
> print *,iTEST,'do some test!'
> else
> print *,iTEST,'no need to do some test!'
> end if
> 1b/ or
> if(iTEST==1)then
> print *,iTEST,'do some test!'
> else
> print *,iTEST,'no need to do some test!'
> end if
>
> 2a/ logical :: lTEST
> if(present(lTEST))then
> print *,lTEST,'do some test!'
> else
> print *,lTEST,'no need to do some test!'
> end if
> 2b/ or
> if((lTEST))then
> print *,lTEST,'do some test!'
> else
> print *,lTEST,'no need to do some test!'
> end if
>
> I don't know which one is a meaningful one.
>
> It goes much complicated when there are also optional arguments to be
> set when optional argument TEST is a must. I'd like to set two
> parameters: ipar1,ipar2.
> I am also how is the best way to set the if ... else ....end
> if.
>
> Any suggested example would be very much appreciated.
This is how I usually approach it. The example below is for when I want to regulate
procedure output via a "quiet" optional argument:
subroutine blah(...other dummy args..., quiet)
! arguments
...other dummy args....
integer, optional, intent(in) :: quiet
! local variables
logical :: noisy
! Default is to output all messages...
noisy = .true.
! ...unless the quiet argument is set.
if ( present(quiet) ) then
if ( quiet == 1 ) noisy = .false.
end if
...other stuff....
if ( noisy ) then
...output stuff....
end if
end subroutine blah
The main reasons I do it like the above are:
1) I want to get all the "is the argument present" tests out of the way up front.
2) I prefer to test for the affirmative, default case in the IF() construct.
3) It allows me to programmatically choose the opposite action, unlike if I was simply
testing on the presence of an argument.
Wrt (3) above, I mean I can do
call blah(...other actual args..., quiet=user_input_value)
to turn the action on or off. If the test in the subroutine was simply,
noisy = .true.
if ( present(quiet) ) noisy = .false.
I couldn't do that. I like the flexibility.
But, it can be onerous if you have many optional "switch" type of arguments.
cheers,
paulv
| |
| jamesgiles@att.net 2008-03-10, 7:52 pm |
| It has been recommended more than once before that the present
behavior of OPTIONAL be extended. The idea is that an OPTIONAL
argument should be allowed to be given an initial value in its
declaration so that if there is no actual argument the dummy becomes
associated with a temporary that initially contains that value.
Hence:
Subroutine ABC(...., opt1, ...)
...
sometype, ...some_attributes..., OPTIONAL :: opt1 = x + 50*y
...
In the body of ABC, the OPT1 variable behaves everywhere as a normally
associated dummy argument except that if there really was no actual
argument the PRESENT inquiry function returns false for it. When I
say it otherwise behaves as a normally associated dummy, I even mean
that if you pass it to yet another procedure it will appear PRESENT
there.
The initial value should not be limited to an "initialization
expression". There is a concept in the standard called a "restricted
expression" (a "specification expression is limited to be a
"restricted expression" that evaluates to a scalar integer). The
initial value of an optional argument should be permitted to be a
"restricted expression" without any limits on shape or type. So the
following should work:
Subroutine XYZ(arg1, ..., opt2, ...)
...
Real, ...attributes... :: arg1(:,:)
Real, ...attributes..., OPTIONAL :: opt2(:,:) = arg1 + 50.0
...
Here the initial value of OPT2 is whatever shape and value the caller
provides if an actual argument is present, otherwise OPT2 is the same
shapes as ARG1 and each element is 50.0 larger. OPT2 then behaves as
any other properly associated argument. If the attributes given
permit it, the value of OPT2 can be changed with assignments,
reallocated, or whatever.
This is upward compatible with the existing standard. Although I'd
like to see the existing behavior of OPTIONAL removed from the
language and allow only this new form, such a step isn't necessary.
--
J. Giles
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
| |
| glen herrmannsfeldt 2008-03-10, 7:52 pm |
| jamesgiles@att.net wrote:
> It has been recommended more than once before that the present
> behavior of OPTIONAL be extended. The idea is that an OPTIONAL
> argument should be allowed to be given an initial value in its
> declaration so that if there is no actual argument the dummy becomes
> associated with a temporary that initially contains that value.
> Hence:
> Subroutine ABC(...., opt1, ...)
> ...
> sometype, ...some_attributes..., OPTIONAL :: opt1 = x + 50*y
Or allow the variable to be used even if it isn't present:
if(.not.present(opt1)) opt1=x+50*y
this avoids the confusion with initialized variables having the SAVE
attribute, though that is also possible...
There have been systems where variables in ENTRY statements were allowed
to be referenced even when the actual entry was a different entry
point, as long as they were previously defined through the appropriate
entry point. Somewhat similar to having the SAVE attribute.
-- glen
| |
| James Van Buskirk 2008-03-10, 7:52 pm |
| "Paul van Delst" <Paul.vanDelst@noaa.gov> wrote in message
news:fr3dhm$neg$1@news.nems.noaa.gov...
> integer, optional, intent(in) :: quiet
> ! Default is to output all messages...
> noisy = .true.
> ! ...unless the quiet argument is set.
> if ( present(quiet) ) then
> if ( quiet == 1 ) noisy = .false.
> end if
Why are you writing this in C? What would have been wrong with
declaring quiet as LOGICAL and then changing the IF statement to
noisy = .NOT.quiet
?
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
| |
| jamesgiles@att.net 2008-03-10, 7:52 pm |
| On Mar 10, 11:27=A0am, glen herrmannsfeldt <g...@ugcs.caltech.edu>
wrote:
> jamesgi...@att.net wrote:
>
> Or allow the variable to be used even if it isn't present:
>
> =A0 =A0 =A0 =A0if(.not.present(opt1)) opt1=3Dx+50*y
I don't like that as well since you still actually do have to test for
the presence of the argument even though in most cases it really
doesn't matter. I clutters the code. Further, you have to worry
whether the control path has passed through that assignment or not.
That means that PRESENTness becomes a dynamic property of the variable
as regards passing it to yet further procedures. One of the
advantages of having things in the declaration is that you don't have
to be worried about whether it occurs or not. You can be sure that
entering the procedure does it.
> this avoids the confusion with initialized variables having the SAVE
> attribute, though that is also possible...
So, initialized variables must now either have the SAVE attribute or
the OPTIONAL attribute. Dummies can't be SAVEd and OPTIONALs must be
dummies. There's not all that much confusion there. To be sure,
there's not much semantic similarity between SAVE and this new use of
OPTIONAL. These OPTIONALs do *not* preserve any value between calls.
If the default value is static (i.e. it obeys the rules for
"initialization expressions") it may superficially seem to be
preserved I guess. But it's really a separate temporary that the
dummy is associated with each time. (Sure, any part of the initial
value expression that *can* be statically evaluated will probably be
separately stored by the implementation. But that is not what's
associated with the dummy.)
> There have been systems where variables in ENTRY statements were allowed
> to be referenced even when the actual entry was a different entry
> point, as long as they were previously defined through the appropriate
> entry point. =A0Somewhat similar to having the SAVE attribute.
Well I certainly wouldn't want to promote something that arcane.
Sounds like a recipe for severe problems (like plausible wrong answers
so that the user isn't readily aware that there's even a bug present,
much less is (s)he easily able to find it).
--
J. Giles
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
| |
| Paul van Delst 2008-03-10, 7:52 pm |
| James Van Buskirk wrote:
> "Paul van Delst" <Paul.vanDelst@noaa.gov> wrote in message
> news:fr3dhm$neg$1@news.nems.noaa.gov...
>
>
>
> Why are you writing this in C? What would have been wrong with
> declaring quiet as LOGICAL and then changing the IF statement to
>
> noisy = .NOT.quiet
>
> ?
Purely personal historical reasons. My use of "keyword" arguments in Fortran95 is based on
how I use similar in IDL (which I was using prior to an f90 compiler being available). In
IDL there is no logical type and when one has
quiet = 1
then
if ( quiet ) then
and
if ( quiet eq 1 ) then
are synonymous. Conversely, so are
if ( not quiet ) then
and
if ( quiet eq 0 ) then
(The rules about what constitutes a "true" or "false" value in IDL are a little bit more
arcane than that, but you get the idea.)
I was going to pontificate about how people seem to grok an integer 0/1 for off/on or
false/true, better than they do an actual .false./.true., but I don't know if that really
is so. My gut tells me it *may* be, but I have zero proof (anecdotal or otherwise).
cheers,
paulv
| |
| James Van Buskirk 2008-03-10, 7:52 pm |
| "Paul van Delst" <Paul.vanDelst@noaa.gov> wrote in message
news:fr3tbb$1b6$1@news.nems.noaa.gov...
> I was going to pontificate about how people seem to grok an integer 0/1
> for off/on or false/true, better than they do an actual .false./.true.,
> but I don't know if that really is so. My gut tells me it *may* be, but I
> have zero proof (anecdotal or otherwise).
So you are following a convention that 1 = .TRUE. and everything else
is .FALSE. A nice complement to C usage...
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
| |
| Richard Maine 2008-03-10, 7:52 pm |
| Paul van Delst <Paul.vanDelst@noaa.gov> wrote:
> I was going to pontificate about how people seem to grok an integer 0/1
> for off/on or false/true, better than they do an actual .false./.true.,
> but I don't know if that really is so. My gut tells me it *may* be, but I
> have zero proof (anecdotal or otherwise).
I don't. In fact, I quite often get it backwards. Actually, I grok 0/1
for off/on just fine. But not for false/true. I particularly tend to get
it backwards when it is a function return value where 0 means that the
function suceeded, and anything else is an error code. It just seems
backwards to me that "all ok" is the true value. I'd intuit instead that
true should indicate success. I have to deliberately check the 0=fa;se
stuff or I get it wrong; it just isn't intuitive to me at al.
--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
| |
| Gordon Sande 2008-03-10, 7:52 pm |
| On 2008-03-10 16:51:56 -0300, nospam@see.signature (Richard Maine) said:
> Paul van Delst <Paul.vanDelst@noaa.gov> wrote:
>
>
> I don't. In fact, I quite often get it backwards. Actually, I grok 0/1
> for off/on just fine. But not for false/true. I particularly tend to get
> it backwards when it is a function return value where 0 means that the
> function suceeded, and anything else is an error code. It just seems
> backwards to me that "all ok" is the true value. I'd intuit instead that
> true should indicate success. I have to deliberately check the 0=fa;se
> stuff or I get it wrong; it just isn't intuitive to me at al.
Ahmen!
I got it wrong often enough that I eventually switched to 1 and 2 with
the alliterative phrase "two is true" to keep it straight. Thankfully
logical has been available for a long time and all echoes/faint images
of F66 can be removed and forgotten.
I have parameters called YES and NO in many of my programs. I use zero
as the non-error state for codes with multiple error modes. Sometimes
I even use negative values for error and positive for various forms of
success when there can be "grades" of success with zero for the "default"
success mode.
| |
| Paul van Delst 2008-03-10, 7:52 pm |
| James Van Buskirk wrote:
> "Paul van Delst" <Paul.vanDelst@noaa.gov> wrote in message
> news:fr3tbb$1b6$1@news.nems.noaa.gov...
>
>
> So you are following a convention that 1 = .TRUE. and everything else
> is .FALSE.
Yes.
> A nice complement to C usage...
O.k. :o)
cheers,
paulv
| |
| Paul van Delst 2008-03-10, 7:52 pm |
| Richard Maine wrote:
> Paul van Delst <Paul.vanDelst@noaa.gov> wrote:
>
>
> I don't. In fact, I quite often get it backwards. Actually, I grok 0/1
> for off/on just fine. But not for false/true. I particularly tend to get
> it backwards when it is a function return value where 0 means that the
> function suceeded, and anything else is an error code. It just seems
> backwards to me that "all ok" is the true value. I'd intuit instead that
> true should indicate success. I have to deliberately check the 0=fa;se
> stuff or I get it wrong; it just isn't intuitive to me at al.
I agree. I should've deleted that last paragraph of mine before I posted. But, for good or
ill, the 0 == "off" and 1 == "on" is a convention in my code. FWIW, I do provide SET and
NOT_SET parameters for usage, e.g.
Quiet = SET
or
Quiet = NOT_SET
just in case people don;t read the documentation.
I think I also decided to go with integer "keyword" argument values across the board for
the additive capability, e.g. using BTEST or IAND to check bit settings. If I recall
correctly, I started to get sick of doing the
! Default is to output all messages...
noisy = .true.
! ...unless the quiet argument is set.
if ( present(quiet) ) then
if ( quiet == 1 ) noisy = .false.
end if
type of thing for a routine where I had a bunch of these on-or-off type of arguments and
the prospect of more (changing the interface everytime too. Ugh.). So I went with a bit
flag argument doing stuff like
Flag = flag_value
and then doing
if ( btest(flag_value,FLAG1 ) )
if ( btest(flag_value,FLAG2 ) )
..etc.. type of thing
For whatever idiosyncratic reason, if I have an integer optional arg in one place, I want
the same everywhere else. <insert shrug+grin here>
:o)
cheers,
paulv
|
|
|
|
|