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

Support optional named arguments without a final unit in uncurried functions. #5907

Merged
merged 4 commits into from
Jan 14, 2023

Conversation

cristianoc
Copy link
Collaborator

@cristianoc cristianoc commented Dec 14, 2022

Functions with optional named arguments normally require a final unit (or some other unnamed argument) to specify the end of supplied arguments: https://rescript-lang.org/docs/manual/latest/function#optional-labeled-arguments
With uncurried functions, the number of arguments is fixed, and there is no such ambiguity.
This PR supports the use of optional named arguments without a final unit.

For example:

let foo = (. ~x=3, ~y) => x+y

can now be applied omitting x as

let n = foo(. ~y=11)

There's one special case where all arguments are optional:

let allOpt = (. ~x=3, ~y=4) => x+y

this can be applied without arguments as follows

let z = allOpt(. )

Note that this application foo(. ) normally supplies a single argument of type unit. However, the type of foo is enough to disambiguate an interpret it as passing zero arguments when foo does not take any unnamed arguments.

This means in practice that uncurried functions are now strictly more expressive than curried ones.

  • Figure out what to do with the warning "This optional parameter in final position will, in practice, not be optional": disabled for uncurried functions via the type checker.
  • Figure out the case of all optional arguments: interpret foo(. ), as empty application when foo is an uncurried function which only has optional arguments.

… argument

Functions such as this one

```res
let foo1 = (~x=3, ~y) => x+y
```

 normally require a final unit unlabeled argument to indicate that the optional argument `x` is not passed.

In this example, writing

```res
let r1 = foo1(~y=11)
```

makes `r1` a function that is still expecting the `x` argument.

Requiring a final unit argument, and passing it as `foo1(~y=11, ())` is the only way to omit `x` in  practice.

With uncurried functions, there's the opportunity to treat `foo1(~y=11)` in a special way, meaning that argument `x` is omitted.

TODO:
- Figure out what to do with the warning ""This optional parameter in final position will, in practice, not be optional"
- Figure out the case of all optional arguments. There's no way to pass zero arguments. One could interpret `foo()`, which actually passes `()` as single unlabelled argument, in a special way when `foo` does not accept unlabelled arguments, and use it to mean zero arguments passed.
…type checker.

In reality this disables also the check for the body, but this check is on the way out so this should be reasonable in practice without over-complicating the error logic.
When all the processed arguments to the function are ignored (hence optional), and no arguments are ignored (so no mandatory labelled), it means the uncurried function only has optional arguments.

- If the uncurried type of the function had an unlabelled arg, then it would be caught by the unit application, so it would be a non-ignored argument. But this is not possible as all the argiments are ignored.
- If it had a labelled mandatory argument, then either it would be non-ignored, or omitted, but both cases are excluded.
- It follows that the type only has optional arguments, and that the unit argument was the only argument supplied.

The new mechanism does not kick in when some legit argument is passed alongside the unit. And noes not interfere with cases where the function expects a legitimate unit argument.
@cristianoc cristianoc changed the title Explore default arguments in uncurried functions without a final unit… Support optional name arguments without a final unit in uncurried functions. Jan 13, 2023
@cristianoc cristianoc changed the title Support optional name arguments without a final unit in uncurried functions. Support optional named arguments without a final unit in uncurried functions. Jan 13, 2023
@cristianoc cristianoc added this to the v11.0 milestone Jan 13, 2023
@cristianoc cristianoc requested a review from zth January 13, 2023 11:29
@cristianoc cristianoc merged commit 01eb614 into master Jan 14, 2023
@cristianoc cristianoc deleted the uncurried_default_no_unit branch January 14, 2023 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants