Skip to content
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

Revised version of the default arguments proposal #175

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

wclodius2
Copy link
Contributor

I have written a revision of the paper by @milancurcic, @jvdp1, and @zjibben that attempts to address most of the issues raised at the Feb. 25 meeting, and a few other issues that have come to my mind. The paper differs from the original primarily by:

Restricting optional arguments to arguments with the INTENT(IN), VALUE, or no intent attributes.

Requiring arguments with a default assignment to be explicitly given the DEFAULT attribute.

Forbidding arguments from having both the DEFAULT and OPTIONAL attributes so that the PRESENT function retains its semantics.

Allowing the expression on the right of the default assignment be a restricted expression and not just a constant expression.

Strongly encouraging that the default assignment be in the FUNCTION or SUBROUTINE statement (and not the TYPE declaration statement) as probably being easier to parse.

Discussing the implications of the constraints on intrinsic assignment, 10.2.1.2, their interpretation, 10.2.1.3, and the constraints on defined assignment, 10.2.1.4, and their interpretation, 10.2.1.5 on default array assignments.

Briefly discussing the implications of an argument with the DEFAULT attribute also having any one of the POINTER, VOLATILE, ASYNCHRONOUS, or TARGET attributes.

@certik
Copy link
Member

certik commented Jul 12, 2020 via email

@wclodius2
Copy link
Contributor Author

wclodius2 commented Jul 12, 2020 via email

@wclodius2
Copy link
Contributor Author

wclodius2 commented Jul 12, 2020

After checking my Ada textbook, I found that one thing I wrote about Ada is wrong so I am going to correct the proposal.

@wclodius2
Copy link
Contributor Author

Removed the comment implying Ada was the exception in having a specification part.

@klausler
Copy link

Restricting optional arguments to arguments with the INTENT(IN), VALUE, or no intent attributes.

This would invalidate existing code, yes?

@milancurcic
Copy link
Member

@klausler I'm pretty sure @wclodius2 meant "Restricting default arguments...". This proposal won't invalidate existing code. If it does, we will fix it.

Copy link
Contributor

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this revision.
I added minor comments around "no intent" and intent(inout). I am not sure what the issues are.

Fortran 2018 does not allow setting a default value for optional
arguments. A default value is the value that the dummy argument
would take if the corresponding actual argument is not present. If a
dummy argument of INTENT(IN) or VALUE, or no intent is declared as
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is no intent equivalent to intent(inout)?

This proposal addresses the issue for INTENT(IN), VALUE, and no intent
arguments that checking for the presence of the optional dummy
argument and using a helper variable is cumbersome and error-prone. We
will not address default values for INTENT(OUT) OR INTENT(INOUT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure to understand why intent(inout) is not considered.If no argument is passed, then intent(inout) would behave as intent(in)?

languages C++ and Ada may be the best known with default arguments. Of
these languages, Ada may be the most pertinent as it has INTENT
arguments similar to Fortran's. Ada has only defined default arguments
useful for INTENT(IN), and has not defined it for INTENT(OUT) or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know Ada. What does it implement for "no intent"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ada doesn't have that option. For its parameters (the Fortran arguments) you always have to specify INTENT with either IN, OUT, or INOUT.

@jvdp1
Copy link
Contributor

jvdp1 commented Jul 12, 2020

This would invalidate existing code, yes?

After having read the document, you should indeed read "Restricting default arguments...".

@wclodius2
Copy link
Contributor Author

wclodius2 commented Jul 12, 2020 via email

@wclodius2
Copy link
Contributor Author

wclodius2 commented Jul 12, 2020 via email

@jvdp1
Copy link
Contributor

jvdp1 commented Jul 12, 2020

Unfortunately no intent is not equivalent to intent(inout), though I wouldn’t object strongly if the revised proposal dropped allowing default assignment for no intent. INTENT(INOUT) means that the input value is always intended to be used and an output value is always expected. No INTENT could behave as an INTENT(IN), INTENT(OUT), or INTENT(INOUT), and its behavior could depend dynamically on the other arguments.

Thank you for the precisions. Therefore, because "no intent" could behave as an intent(out), wouldn't it make sense to not allowing default assignment for "no intent"? Otherwise, users could just drop "intent(out)" and add a default value for an argument actually behaving as intent(out)

@wclodius2
Copy link
Contributor Author

wclodius2 commented Jul 12, 2020 via email

Minor improvements in wording over 20-108.txt. More use cases. Changed NAMESPACE attributes to WITH attribute.
Instead of assuming that arguments with no intent are treated the same as arguments with the INTENT(IN) or VALUE attributes, I discuss no intent arguments separately and leave it up to others to decide how to treat no intent arguments.
@certik
Copy link
Member

certik commented Jan 20, 2021

I don't like specifying the default value in the argument list as in real function quadratic(x, a, b, c=0). I am ok with using default (and not mix this with optional).

One objection from the committee I believe is that the syntax integer, intent(in), default :: c = 0 implies the save attribute. So perhaps this syntax should be used instead: integer, intent(in), default(0) :: c.

@milancurcic
Copy link
Member

One objection from the committee I believe is that the syntax integer, intent(in), default :: c = 0 implies the save attribute.

I don't understand this objection because dummy arguments can't have a save attribute.

I am also okay with not mixing default and optional. I slightly prefer the default :: c = 0 syntax, but default(0) :: c is fine too.

@klausler
Copy link

You need to decide whether the default value of a dummy argument (or just that fact that it has one) is meant to be a characteristic of the procedure or not. This matters in the implementation, because it determines whether an implementation has the freedom to implement the default value in the caller (as in C++) or in the called subprogram, or whether the language is forcing one or the other.

Why this matters: if the default value of a dummy argument is an expression involving other dummy arguments, host-associated variables, module or COMMON objects, &c., implementing the evaluation of the default value in the caller can be difficult or impossible. But if default values are expressions to be evaluated if need be in the called subprogram, then the value need not be part of the characteristics or interface, and the implementation of the calling side is no different from an OPTIONAL argument; and one could argue that an explicit interface need not distinguish between OPTIONAL and having a default value for purposes of procedure pointer assignment and other interface compatibility checking.

@certik
Copy link
Member

certik commented Jan 20, 2021

Peter, when I discussed that at the last meeting (after the plenary), I think our idea was to implement the default value in the caller, which enables the compiler to compile the subroutine ahead of time without any if statements, and call it exactly the same way no matter if the user provides the default argument or not.

You have a good point about what if the default value is an expression involving other dummy arguments that it might be impossible. I don't know yet if it is impossible, and so a prior compiler implementation would be in order here. At least in gfortran it seems any of these expressions (such as a length of an array) is part of the function signature, so this would be also.

@klausler
Copy link

Peter, when I discussed that at the last meeting (after the plenary), I think our idea was to implement the default value in the caller, which enables the compiler to compile the subroutine ahead of time without any if statements, and call it exactly the same way no matter if the user provides the default argument or not.

You have a good point about what if the default value is an expression involving other dummy arguments that it might be impossible. I don't know yet if it is impossible, and so a prior compiler implementation would be in order here. At least in gfortran it seems any of these expressions (such as a length of an array) is part of the function signature, so this would be also.

subroutine host(defaultY)
  real, intent(in) :: defaultY
  call solver(f)
 contains
  real function f(x, y)
    real, intent(in) :: x, y
    default(defaultY) :: y
    ...
  end function
end subroutine

Seems like a compelling use case to me, but the default has to be implemented in the called subprogram to make it work. So there's reasons why defaults should be implemented in callees, and the only argument for implementing them in callers (it might save a predictable branch) is weak and also has other obvious solutions.

@certik
Copy link
Member

certik commented Jan 20, 2021

I see. The nested subroutine f has access to the variables in the parent scope, such as defaultY, so this would work if the default is not part of the signature, using the current mechanism for nested subroutines. But if it is part of the signature of f, then one needs access to defaultY inside the function solver, which currently is not possible. Good point, thank you @klausler.

@klausler
Copy link

I see. The nested subroutine f has access to the variables in the parent scope, such as defaultY, so this would work if the default is not part of the signature, using the current mechanism for nested subroutines. But if it is part of the signature of f, then one needs access to defaultY inside the function solver, which currently is not possible. Good point, thank you @klausler.

Here's an idea: extend the VALUE attribute to accept an expression, and allow it to be applied to an OPTIONAL dummy argument as its default value. (You could also accept VALUE with an expression to specify a per-invocation initializer for a local variable, too, I suppose.)

@certik certik added the Clause 8 Standard Clause 8: Attribute declarations and specifications label Apr 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 8 Standard Clause 8: Attribute declarations and specifications
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants