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

Consider revising function argument defaulting #27

Closed
jclark opened this issue Mar 24, 2019 · 11 comments
Closed

Consider revising function argument defaulting #27

jclark opened this issue Mar 24, 2019 · 11 comments
Labels
Area/Lang Relates to the Ballerina language specification incompatible Resolving issue may not be backwards compatible status/pending Design is agreed and waiting to be added Type/Improvement Enhancement to language design
Milestone

Comments

@jclark
Copy link
Collaborator

jclark commented Mar 24, 2019

We should consider whether and, if so, how the design of function argument defaulting should be revised so as to

@jclark jclark added Type/Improvement Enhancement to language design Area/Lang Relates to the Ballerina language specification incompatible Resolving issue may not be backwards compatible labels Mar 24, 2019
@jclark jclark added this to the 2019R2 milestone Mar 24, 2019
@jclark
Copy link
Collaborator Author

jclark commented Mar 26, 2019

Scala (which shares our named argument syntax) has an interesting design, which I think we can borrow from:

https://docs.scala-lang.org/sips/completed/named-and-default-arguments.html
https://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#named-and-default-arguments

@jclark
Copy link
Collaborator Author

jclark commented Mar 26, 2019

If we apply the Scala approach in the context of Ballerina, we would end up with something like this.

  • Adding = expr in a parameter means only that the parameter has a default and thus does not need to be specified
  • In a function call, a parameter can always be specified using its name.
  • The caller of the function maps parameter names onto parameter positions using the function's type descriptor
  • The name of a parameter does not affect the shape of the function and so does not affect function subtyping
  • Parameter defaults are expressions (not necessarily compile-time constant expressions) that are evaluated for each function call.
  • Expressions for parameter defaults can refer to earlier parameters and will get the actual value for this call not the default.
  • Whether a particular parameter has a default is part of the shape of the function and affects subtyping, but the expression that computes the default is part of the function implementation, not part of the type.

@jclark
Copy link
Collaborator Author

jclark commented Mar 26, 2019

Scala allows a named argument to occur before a positional argument in a function call, but requires that for such an argument the name and position must correspond (i.e. if argument number n has name x and occurs in a function call before a positional argument, then parameter number must also have name x). I am not sure if that is the right rule for us.

@jclark
Copy link
Collaborator Author

jclark commented Mar 26, 2019

I wonder if we need a way to write the type of a function with a defaultable argument without specifying what the default is. Not very useful because you would not be able to call the function without specifying the defaultable argument, because you would not know what to default it to.

@jclark jclark added the status/discuss Needs discussion outside github comments label Mar 26, 2019
@jclark jclark modified the milestones: 2019R2, 2019R1 Mar 28, 2019
@jclark
Copy link
Collaborator Author

jclark commented Mar 28, 2019

We should consider whether we want to allow foo(int x, int y = 0, int z) or whether we should require that once a parameter is given a default, all subsequent parameters should also be given a default.

@jclark
Copy link
Collaborator Author

jclark commented Mar 28, 2019

For function call site, discussion suggests people prefer to have all arguments specified by position coming before all arguments specified by name.

@sameerajayasoma
Copy link
Contributor

I think making all subsequent parameters to require a default after a parameter is given a default value will reduce the flexibility of this design. Yes, enforcing that all the positional arguments should come before named arguments is better IMO.

@jclark
Copy link
Collaborator Author

jclark commented Mar 28, 2019

@sameerajayasoma The latter rule is about the call site. The former rule is about the declaration site. I don’t see the latter as an alternative to the former. Can you give an example of when you would need flexibility prohibited by the former rule?

The reason for the rule is to make it more obvious which parameter a positional argument corresponds to. Without this, people maybe unsure whether a positional argument specifies a defaultable parameter or a subsequent non-defaultable parameter.

@jclark
Copy link
Collaborator Author

jclark commented Mar 28, 2019

Kotlin’s approach seems similar

https://kotlinlang.org/docs/reference/functions.html#named-arguments

@jclark
Copy link
Collaborator Author

jclark commented Mar 29, 2019

We can distinguish two different approaches, depending on whether the defaultability of a parameter is part of the shape (ie affects subtyping).

The more straightforward approach is where defaultability is not part of the shape. The mapping of parameter names to positions and providing defaults for unspecified arguments is handled by the caller. The callee sees the ordered list of arguments ready to go. The typedesc conceptually provides both a parameter name-to-position map, and for each defaultable parameter a closure that computes the default value from the value of previous parameters (in a similar way to records).

It has the disadvantage that this does not work:

type F1 function(int x);
function foo(int x, int y = 0);
F1 f = foo;  // not allowed

One could have some built-in methods on the typedesc to generate wrappers automatically.

With this approach subtyping is straightforward, with the rest argument being the only complication.

@jclark
Copy link
Collaborator Author

jclark commented Mar 29, 2019

Tentative conclusions after discussion between me and @sanjiva are:

  • Defaultability (along with parameter name) is not part of the shape and does not affect subtyping, as described in previous comment.
  • In a function call, after an argument is specified by name, all subsequent arguments must be specified by name
  • In a function declaration, after a default is specified for a parameter, a default must be specified for all subsequent parameters

@jclark jclark added status/pending Design is agreed and waiting to be added and removed status/discuss Needs discussion outside github comments labels Mar 29, 2019
@jclark jclark closed this as completed in f9ca76c Apr 1, 2019
jclark added a commit that referenced this issue Apr 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area/Lang Relates to the Ballerina language specification incompatible Resolving issue may not be backwards compatible status/pending Design is agreed and waiting to be added Type/Improvement Enhancement to language design
Projects
None yet
Development

No branches or pull requests

2 participants