Skip to content

proposal for setting default values of optional arguments #137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 11, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions proposals/default_optional_arguments/proposal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
To: J3 J3/XX-XXX
From: Milan Curcic
Subject: Default value for optional arguments
Date: 2020-January-10

Proposal for Fortran Standard: 202y (NOT 202x)


Prior art: https://j3-fortran.org/doc/year/18/18-136r1.txt


1. Problem

Currently, standard Fortran does not allow setting a default value
for optional arguments. Default value of an optional argument is
the value that the dummy argument would take if the corresponding
actual argument is not present. If declaring a dummy argument as
optional, the user must:

* Explicitly test for the presence of the actual argument using
the intrinsic function present();
* Use a separate variable inside the procedure to assign the value
because the optional dummy argument that is not present must not
be referenced in expressions other than as actual argument to
the intrinsic function present().

This example function illustrates the problem:

real function quadratic(x, a, b, c)
! returns a + b * x + c * x**2 if c is present
! and a + b * x otherwise
real, intent(in) :: x, a, b
real, intent(in), optional :: c
real :: c_tmp ! use another var. to reference the missing arg
c_tmp = 0 ! default value if c is not present
if (present(c)) c_tmp = c
quadratic = a + b * x + c_tmp * x**2
end function quadratic

For any dummy argument with the optional attribute, the programmer
must use the intrinsic function present() to check for the presence
of the argument. Furthermore, if the optional dummy argument is
meant to be used in multiple places in the procedure, the programmer
is likely to use the pattern from the example above, where a
"temporary" variable is declared and used in place of the dummy
argument, which disconnects the implementation from the user
interface. Furthermore, this requires at least 3 lines of code
(declaration of c_tmp, initialization of c_tmp, and testing for the
presence of c) only to handle the scenario of a missing optional
argument.

This proposal seeks to address the issue that explicitly checking
for presence of the optional dummy argument and using a helper
variable is cumbersome and error-prone. The primary benefit of this
feature is the reduction in source code needed to handle optional
arguments. This benefit is even greater in scenarios where the
optional argument is used in many places in the procedure, and a
helper variable is used for its value instead. Reduction in needed
source code would result in more readable and more correct programs.
The secondary benefit of this is programmer happiness, as working
with optional arguments would require less typing.

2. Proposed solution

As suggested by Van Snyder in 18-136r1, the problem could be solved
by allowing an optional argument to be initialized using a constant
expression. The optional argument would then only be initialized if
the corresponding actual argument is not provided by the caller.
Example:

real function quadratic(x, a, b, c)
! returns a + b * x + c * x**2 if c is present
! and a + b * x otherwise
real, intent(in) :: x, a, b
real, intent(in), optional :: c = 0
quadratic = a + b * x + c * x**2
end function quadratic

In this snippet, we use the assignment operator (=) to specify the
default value of the optional dummy argument.

Like initializer, the optional argument can be assigned any constant
expression, as defined in Section 10.1.12 of 18-007r1.

While there may be concerns that the same syntax is used to
implicitly set the save attribute for variables in procedures, there
is no conflict because the language prohibits dummy arguments
from having an initializer, or the save attribute. The change to the
standard to allow this feature would thus be to allow an optional
dummy argument to have an initializer, which would be triggered only
when corresponding actual argument is not passed by the caller.

This improvement has already been suggested by Van Snyder in
18-136r1, has received votes in the user survey for 202X (see
https://isotc.iso.org/livelink/livelink?func=ll&objId=19530634&objAction=Open&viewType=1),
and appeared on Data subgroup's wishlist at meeting 215 (see
https://j3-fortran.org/doc/year/18/18-122r1.txt).

3. Backward compatibility

This addition to the language would not break any existing standard
conforming Fortran program, and thus preserves Fortran's backward
compatibility.

4. Further discussion

Online discussion that led to this proposal can be found at
https://github.com/j3-fortran/fortran_proposals/issue/22.