OPTIONAL and PRESENT
| Optional dummies | |
| Test with present | |
| Defaults inside | |
| Guard before use |
Optional dummies
Optional marks a dummy that callers may skip: declare it with the optional attribute and both call shapes become legal.
Keep required arguments first and optional ones last, so every call reads naturally from left to right.
program optbasic
implicit none
call greet("Ada")
call greet("Ada", "Dr")
contains
subroutine greet(name, title)
implicit none
character(len=*), intent(in) :: name
character(len=*), intent(in), optional :: title
if (present(title)) then
print *, title, name
else
print *, name
end if
end subroutine greet
end program optbasic
./optbasic
Ada
Dr Ada
Test with present
Present tests for the missing argument: it returns true only when the caller passed something, so branch on it before touching the value.
The second line appears only for the call that supplies the code, which proves the test works.
program presenttest
implicit none
call report(7)
call report(7, 99)
contains
subroutine report(x, code)
implicit none
integer, intent(in) :: x
integer, intent(in), optional :: code
print *, x
if (present(code)) then
print *, code
end if
end subroutine report
end program presenttest
./presenttest
7
7
99
Defaults inside
Defaults live inside the procedure: copy to a local, overwrite it when present, and the rest of the code uses one variable.
This pattern keeps a single code path for both call shapes instead of duplicating the logic.
program optdefault
implicit none
call launch("test")
call launch("test", 3)
contains
subroutine launch(job, workers)
implicit none
character(len=*), intent(in) :: job
integer, intent(in), optional :: workers
integer :: n
n = 1
if (present(workers)) n = workers
print *, job, n
end subroutine launch
end program optdefault
./optdefault
test 1
test 3
Guard before use
Never reference an optional dummy without a present guard: an absent argument has no storage, and touching it is undefined.
Settle the count up front, then loop with a plain variable that is always safe to read.
program optdemo
implicit none
call announce("ready")
call announce("ready", 3)
contains
subroutine announce(msg, times)
implicit none
character(len=*), intent(in) :: msg
integer, intent(in), optional :: times
integer :: i
integer :: n
n = 1
if (present(times)) n = times
do i = 1, n
print *, msg
end do
end subroutine announce
end program optdemo
./optdemo
ready
ready
ready
ready
Next: Explicit interfaces
Article author: Arthur Isaev