Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing optional arguments down the call tree

37 views
Skip to first unread message

Adrian

unread,
Nov 7, 2003, 3:43:24 AM11/7/03
to
I have a need to pass the presence or otherwise of optional aguments
down the call tree, eg:

program...
call first(...)
end

subroutine first(a,b,c)
integer a
integer, optional :: b,c

c-- how do I call second??
c-- like this??

if ( present(b) .and. present(c)) then
call second(a,b=b,c=c)
elseif(.not. present(b) .and. present(c)) then
call second(a,c=c)
elseif( present(b) .and. .not. present(c)) then
call second(a,b=b)
else
call second(a)
endif

c-- this seems very messy particularly if there are more than 2
c-- optional arguments, any more generic method?

return
end

subroutine second(a,b,c)
integer a
integer, optional :: b,c
...
return
end

Jan C. Vorbrüggen

unread,
Nov 7, 2003, 4:05:03 AM11/7/03
to
Ugh. I seem to remember that for the one action of using an optional
dummy argument as an actual argument to a subroutine or function, you
can do this _without_ checking for its presence.

Jan

Michael Metcalf

unread,
Nov 7, 2003, 4:31:44 AM11/7/03
to

"Adrian" <ac...@hotmail.com> wrote in message
news:6f89be88.03110...@posting.google.com...

> I have a need to pass the presence or otherwise of optional aguments
> down the call tree, eg:
>

You can do exactly what you want, however, you MUST have an explicit
interface. I have modified your code to acheive this using internal
proceures; using a module containing those procedure would be equally valid
("Fortran 90/95 Explained", Section 5.13).

Regards,

Mike Metcalf

program optional
call first(5)
call first(6, c=4)

contains

subroutine first(a,b,c)
integer a
integer, optional :: b,c

call second(a,b=b,c=c)
call second(a,c=c)
call second(a,b=b)
call second(a)
return
end subroutine

subroutine second(a,b,c)
integer a
integer, optional :: b,c

print *, a, present(b), present(c)
return
end subroutine
end program


Richard Maine

unread,
Nov 7, 2003, 10:54:24 AM11/7/03
to
"Michael Metcalf" <metc...@acm.org> writes:

> "Adrian" <ac...@hotmail.com> wrote in message
> news:6f89be88.03110...@posting.google.com...
>> I have a need to pass the presence or otherwise of optional aguments
>> down the call tree, eg:
>
> You can do exactly what you want, however, you MUST have an explicit
> interface.

And note that you need an explicit interface for *ANY* procedure with an
optional argument. This requirement is not specific to the case of
passing the optionality down the tree.

Note also that you may use either positional or keyword syntax for
the optional arguments (though you can't use a double comma to indicate
an omitted argument). Michael's examples all used the keyword
syntax. The following line would also be valid in Michael's
subroutine first.

call second(a,b,c)

This is ok even if b and c are not present; the non-presense gets
passed down correctly.

One caveat in the general area of optionality: Having an actual
argument that is a nullified pointer is *NOT* the same thing as
omitting the actual argument. There are times when this would be
convenient. Perhaps in some future revision (at least for nonpointer
dummies; making a null actual count as non-present for a pointer
dummy would break existing code).

--
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

Adrian

unread,
Nov 10, 2003, 10:08:12 AM11/10/03
to
Richard Maine <nos...@see.signature> wrote in message news:<m3r80k5...@altair.dfrc.nasa.gov>...

> "Michael Metcalf" <metc...@acm.org> writes:
>
> > "Adrian" <ac...@hotmail.com> wrote in message
> > news:6f89be88.03110...@posting.google.com...
> >> I have a need to pass the presence or otherwise of optional aguments
> >> down the call tree, eg:
> >
> > You can do exactly what you want, however, you MUST have an explicit
> > interface.
>
> And note that you need an explicit interface for *ANY* procedure with an
> optional argument. This requirement is not specific to the case of
> passing the optionality down the tree.
>
> Note also that you may use either positional or keyword syntax for
> the optional arguments (though you can't use a double comma to indicate
> an omitted argument). Michael's examples all used the keyword
> syntax. The following line would also be valid in Michael's
> subroutine first.
>
> call second(a,b,c)
>
> This is ok even if b and c are not present; the non-presense gets
> passed down correctly.

Many thanks, this works just fine. However I now have a further issue
where the variables b and c get manipulated into d and e respectively.
The presence or otherwise of b and c decides whether d and e get
calculated. Now I want to call the next routine, third, with d and e
as arguments. I presume I have to do the full check here as per my
first post:

if ( present(b) .and. present(c)) then

call third(a,d=d,e=e)


elseif(.not. present(b) .and. present(c)) then

call third(a,e=e)


elseif( present(b) .and. .not. present(c)) then

call third(a,d=d)
else
call third(a)
endif

Is there a more elegant way of doing this?

Adrian

Michael Metcalf

unread,
Nov 10, 2003, 10:37:49 AM11/10/03
to

"Adrian" <ac...@hotmail.com> wrote in message
news:6f89be88.03111...@posting.google.com...

>> Many thanks, this works just fine. However I now have a further issue
> where the variables b and c get manipulated into d and e respectively.
> The presence or otherwise of b and c decides whether d and e get
> calculated. Now I want to call the next routine, third, with d and e
> as arguments. I presume I have to do the full check here as per my
> first post:
>
> if ( present(b) .and. present(c)) then
> call third(a,d=d,e=e)
> elseif(.not. present(b) .and. present(c)) then
> call third(a,e=e)
> elseif( present(b) .and. .not. present(c)) then
> call third(a,d=d)
> else
> call third(a)
> endif
>
> Is there a more elegant way of doing this?

Well, you could set d and e to some default value that can be tested in
third, which you call with all 3 arguments, something like:

real :: d = huge(0.), e = huge(0.)
:
if (present(b)) d = fn(b)
:
call third(a, d, e)

Hope that helps,

Mike Metcalf


0 new messages