Skip to content

SIP-NN - Allow referring to other arguments in default parameters #653

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 3 commits into from
Feb 13, 2017
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
105 changes: 105 additions & 0 deletions sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
layout: sip
disqus: true
title: SIP-NN - Allow referring to other arguments in default parameters
Copy link
Contributor

Choose a reason for hiding this comment

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

"Other arguments" or "previous arguments"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe previous I guess if other is not feasible (circle dependencies)?

Copy link
Member

Choose a reason for hiding this comment

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

I would actually write "Allow references to left arguments of the same list in default parameters" if @pathikrit agrees with my previous analysis that doing it for all the arguments is unfeasible. 😄

---

**By: Pathikrit Bhowmick**

## History

| Date | Version |
|---------------|------------------|
| Jan 11th 2017 | Initial Draft |
| Jan 12th 2017 | Initial Feedback |
| Jan 16th 2017 | Minor Changes |

## Introduction
Currently there is no way to refer to other arguments in the default parameters list:
Copy link
Member

@jvican jvican Jan 11, 2017

Choose a reason for hiding this comment

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

Adding a motivation section that showcases why this is useful would be great!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Working on it...


Does not compile:
```scala
def substring(s: String, start: Int = 0, end: Int = s.length): String
```

The workaround to achieve this is by using a curried-function:
```scala
def substring(s: String, start: Int = 0)(end: Int = s.length): String
```

However, the above workaround is not always suitable in all situations since you may not want a curried function.

The other more verbose alternative is by overloading:
```scala
def substring(s: String, start: Int): String
= substring(s, start = 0, end = s.length)
def substring(s: String, start: Int = 0, end: Int): String
```

The above is quite verbose as it required 1 extra function definition per argument that refers other args.

### Proposal
Allow to refer to ***any*** parameters in the same (or left) curried parameter list:
```scala
def substring(s: String, start: Int = 0, end: Int = s.length) // Legal
def substring(start: Int = 0, end: Int = s.length, s: String) // Legal !!!
def substring(s: String, start: Int = 0)(end: Int = s.length) // Legal (works currently)
def substring(start: Int = 0, end: Int = s.length)(s: String) // Illegal
```

The same applies for class arguments:
```scala
class Substring(s: String, start: Int = 0, end: Int = s.length) // Legal
class Substring(start: Int = 0, end: Int = s.length, s: String) // Legal
class Substring(s: String, start: Int = 0)(end: Int = s.length) // Legal
class Substring(start: Int = 0, end: Int = s.length)(s: String) // Illegal
```

We should also be able to refer to ***multiple*** parameters:
```scala
def binarySearch(start: Int, end: Int, middle: Int = (start + end)/2) // Legal
```

# Motivating examples:

TBD

## Interactions with other syntax

#### Partially Applied Functions:
Works as expected:
```scala
def substring(s: String, start: Int = 0, end: Int = s.length)

substring(_, start = 0, end = 5) // Legal
substring(_, end = 5) // Legal (start = 0)
substring(_, start = 5) // Legal (same as s => substring(s, start = 5, end = s.length)
```

#### Multiple Implicit Parameters
[Multiple implicit parameters](https://github.com/scala/scala.github.com/pull/520) should also be allowed to refer to one another (left to right):
```scala
def codec[A](data: A)(implicit encoder: Encoder[A])(implicit decoder: Decoder[A] = encoder.reverse) // Legal
Copy link
Contributor

Choose a reason for hiding this comment

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

Am I missing something, or this is not legal Scala syntax (multiple implicit parameter lists)?

Copy link
Member

Choose a reason for hiding this comment

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

I think that what @pathikrit means is that this change should also be valid for implicit parameter lists. That would marry well with this SIP.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the link to the PR

```

#### Referring to type members:
The default parameters should be able to refer to type members of other arguments e.g.:
Copy link
Member

@jvican jvican Jan 11, 2017

Choose a reason for hiding this comment

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

This section seems orthogonal to the target of this PR (this issue was raised by @olafurpg). I think that the good approach here would be to create another SIP that keeps track of this feature, since I would expect the implementation of this to be different to the one requested. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know much about scalac internals to comment. Maybe it is very similar (then keep 1 SIP) and maybe it isn't (2 SIPs). Can someone more familiar with scalac comment?

Copy link
Member

Choose a reason for hiding this comment

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

I've been looking into the implementation details of this and I can confirm that they are orthogonal issues. Concretely, referring to type members is tricky. I think it can be done but the feature interaction is scary. Could someone confirm? Maybe @xeno-by || @sjrd?

Copy link
Member

Choose a reason for hiding this comment

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

I think they're similar in spirit, but I'm sure they're distinct in the implementation.

To avoid a situation where the committee pushes you back a month to go look into and document this, I would keep it in. At the very least they can ask you to split it out - you can then drop it or pursue it as a separate SIP.

```scala
trait Codec {
type Input
type Output
}

def codec(codec: Codec, in: codec.Input, out: codec.Output) // Legal !!!
```

### Other languages
The following languages allow referring to previously declared arguments in the function signature:
* [CoffeeScript](http://coffeescript.org/)
* [Kotlin](http://kotlinlang.org)
* [TypeScript](https://www.typescriptlang.org/)

AFAIK, there are no major languages where referring to parameters declared to the ***right*** is allowed.

### Discussions
[Scala Lang Forum](https://contributors.scala-lang.org/t/refer-to-previous-argument-in-default-argument-list/215/6)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be useful to have an implementation sketch to accompany this SIP. In my opinion, information about why this proposal hasn't been implemented yet and why it is feasible would help the potential discussion during one of the upcoming SIP meetings.

Copy link
Member

@jvican jvican Jan 12, 2017

Choose a reason for hiding this comment

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

I've been looking into this today and will submit an implementation sketch very soon, along with a design document /cc @pathikrit