(j3.2006) Conditional expressions
Van Snyder
Van.Snyder
Tue Mar 15 22:10:55 EDT 2011
Here's a problem that I'd like to solve using a conditional expression.
None of the alternatives are as satisfactory.
subroutine S ( A, B )
real :: A(:)
real, optional, target :: B(:)
real,target :: C(merge(0,size(a),present(B)))
real, pointer :: P(:)
p => c
if ( present(b) ) p => b
call t ( a, p )
! a lot more code involving p
end subroutine S
Taking the liberty to use the C syntax for a conditional expression, I'd
rather have
subroutine S ( A, B )
real :: A(:)
real, optional :: B(:)
real :: C(merge(0,size(a),present(B)))
associate ( p => present(b) ? b : c )
call t ( a, p )
! a lot more code involving p
end associate
end subroutine S
Notice there are no pointers or targets here. The selector produces
either the object b or the object c, not one of the values, as MERGE
would.
The alternatives are
1. Have two versions of this routine, one with B and one without, glued
together with a generic name, with one using B and the other using C
(but called B, just not a dummy argument). I'd put the execution part,
and matbe some of the specification part, in an include file to reduce
opportunities for divergence during maintenance.
2. A macro would be a nicer solution, allowing to produce the body of
the associate construct twice, once with p=b and once with p=c,
selecting between the macro instantiations using present(b), but... we
axed macros at the last minute.
3. Keep the pointer and targets, but strip off the pointer attribute
with an associate construct, hoping this helps optimizers and runtime
checkers:
associate ( q => p )
same stuff
end associate
4. Put the stuff that uses p (essentially the body of the associate
construct) in an internal subroutine and call it with either B or C as
its argument.
if ( present(b) ) then
call my_internal ( b )
else
call my_internal ( c )
end if
This solution only works, of course, in the case that the place I want
to use it isn't already an internal subroutine.
5. Like 4, but not an internal subroutine. Would require more
arguments since host association wouldn't be available.
6. Make B non-optional and require the caller always to provide it.
7. Just live with pointers and targets.
More information about the J3
mailing list