In fortran, we can define default arguments. However, if an optional argument is not present, it can also not be set. When using arguments as keyword arguments with default values, this leads to awkward constructs like
PROGRAM PDEFAULT
CALL SUB
CALL SUB(3)
CONTAINS
SUBROUTINE SUB(VAL)
INTEGER, OPTIONAL :: VAL
INTEGER :: AVAL ! short for "actual val"
IF(PRESENT(VAL)) THEN
AVAL = VAL
ELSE
AVAL = -1 ! default value
END IF
WRITE(*,'("AVAL is ", I0)') AVAL
END SUBROUTINE SUB
END PROGRAM PDEFAULT
Personally, I often ran into the problem of accidentially typing VAL
instead of AVAL
, i.e. the disconnect between the variable name in the interface, and the initialized value used in the code can introduce runtime bugs – let alone that this manner of initialization is rather verbose.
Is there some more elegant way of using optional arguments with a default value?
Example It would feel more natural to write something like
IF(NOT(PRESENT(VAL))) VAL = -1
because it avoids the VAL
vs AVAL
confusion. But it isn't valid, presumably because Fortran passes arguments by reference and thus if VAL
is not present in the CALL
statement, no memory is associated with VAL
and VAL = -1
would cause a segfault.
You described the situation rather well. There is no other way I am aware of and that is standard conforming. The pattern with a local variable named similarly is what people often use. The other option is to just put if (present()) else
everywhere, but that is awkward.
The point is that they are optional arguments, not default arguments. Fortran doesn't have default arguments. The may have been better, but that is not what the committee members have chosen in the 80s when preparing Fortran 90.