Skip to content

Latest commit

 

History

History
179 lines (138 loc) · 7.57 KB

DIP1030.md

File metadata and controls

179 lines (138 loc) · 7.57 KB

Named Arguments

Field Value
DIP: 1030
Review Count: 0
Author: Walter Bright walter@digitalmars.com
Implementation:
Status: Community Review Round 1

Abstract

Allow arguments in function calls to optionally be prefixed with the name of the function parameter to which they apply, analogous to the manner in which field names can optionally be used in struct initializers to prefix field initializers. This will enable better self documentation, make longer argument lists easier to review, enable reordering of arguments at the user's discretion, and no longer constrain default parameter values to the end of the parameter list.

Contents

Rationale

  1. Although this proposal supports reordering, the real reason for naming is so one can have a function with a longish list of parameters, each with a reasonable default, and users need only supply the arguments that matter for their use case. This is much more flexible than the current method of putting all the defaults at the end of the parameter list, and defaulting one means all the rest get defaulted.
  2. For a longish list of parameters, when users find themselves counting parameters to ensure they line up, then named parameters can be most helpful.
  3. A step towards making it possible to replace the brace struct initialization syntax with a function-call-like construct. I.e. the initialization of structs is unified with struct literals and struct constructors.
  4. Allow replacing std.typecons.Flag which is syntactically awkward.
  5. For situations when code clarity at the caller site is of paramount importance (i.e. for some critical code), to make it unquestionably clear which values go where, even for short argument lists.

Prior Work

Both DIP 1019 and DIP 1020 detail prior work in other languages, which will not be repeated here.

Description

This proposal is based on the recognition that D already has named parameters for struct initializers. Closely related are array initializers and associative array literals.

The syntax is modified to replace the definition of ArgumentList for function call arguments with:

ArgumentList:
-   AssignExpression,
-   AssignExpression,
-   AssignExpression , ArgumentList
+   NamedArgument
+   NamedArgument ,
+   NamedArgument , ArgumentList

+NamedArgument:
+   Identifier : AssignExpression
+   AssignExpression

Assignment of arguments to parameters works the same as assignments to fields.

Matching of NamedArguments to a function's, function pointer's, or delegate's parameters proceeds in lexical order. For each NamedArgument:

  1. If an Identifier is present, it matches the Parameter with the corresponding Identifier. If it does not match any named Parameter, then it is an error.
  2. If an Identifier is not present, the Parameter matched is the one following the previous matched Parameter, or the first Parameter if none have yet been matched.
  3. Matching a Parameter more than once is an error.
  4. After the NamedArgumentList is exhausted, any unmatched Parameters receive the corresponding default value specified for that Parameter. If there is no default value, it is an error.
  5. If there are more NamedArguments than Parameters, the remainder match the trailing ... of variadic parameter lists, and Identifiers are not allowed.

The set of matched functions becomes the overload set, to which the usual overload resolution is applied to select the best match.

I.e., function resolution is done by constructing an argument list separately for each function before testing it for matching. If the parameter name(s) do not match, the function does not match. If a parameter has no corresponding argument, and no default value, then the function does not match.

void snoopy(T t, int i, S s);     // A
void snoopy(S s, int i = 0, T t); // B

S s; T t; int i;
snoopy(t, i, s); // A
snoopy(s, i, t); // B
snoopy(s, t); // error, neither A nor B match
snoopy(t, s); // error, neither A nor B match
snoopy(s:s, t:t, i:i); // error, ambiguous
snoopy(s:s, t:t); // B
snoopy(t:t, s:s); // B
snoopy(t:t, i, s:s); // A
snoopy(s:s, t:t, i); // A

The AssignExpressions are evaluated in the lexical order they appear in the NamedArgumentList.

Explicit Template Instantiation

The same is applied to Explicit Template Instantiation.

The TemplateArgumentList is replaced with:

TemplateNamedArgumentList:
-    TemplateArgument
-    TemplateArgument ,
-    TemplateArgument , TemplateArgumentList
+    TemplateNamedArgument
+    TemplateNamedArgument ,
+    TemplateNamedArgument , TemplateNamedArgumentList

+TemplateNamedArgument:
+    Identifier : TemplateArgument
+    TemplateArgument

The matching rules are the same as described for functions.

Since template arguments are evaluated at compile time, there is no order of evaluation consideration.

Breaking Changes and Deprecations

None

Reference

Copyright & License

Copyright (c) 2019 by the D Language Foundation

Licensed under Creative Commons Zero 1.0

Reviews

The DIP Manager will supplement this section with a summary of each review stage of the DIP process beyond the Draft Review.