From e38ca6de18f9f12b2c1e1f547470c6615b35770f Mon Sep 17 00:00:00 2001 From: Pathikrit Bhowmick Date: Wed, 11 Jan 2017 01:28:50 -0500 Subject: [PATCH 1/3] First draft of SIP to allow referring to other arguments in default parameters --- ...017-01-11-refer-other-arguments-in-args.md | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md diff --git a/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md new file mode 100644 index 0000000000..6674c4be64 --- /dev/null +++ b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md @@ -0,0 +1,90 @@ +--- +layout: sip +disqus: true +title: SIP-NN - SIP Title +--- + +**By: Pathikrit Bhowmick** + +## History + +| Date | Version | +|---------------|---------------| +| Jan 11th 2017 | Initial Draft | + +## Introduction +Currently there is no way to refer to other arguments in the default parameters list: + +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 certain situations. + +### 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*** paramaeters: +```scala +def binarySearch(start: Int, end: Int, middle: Int = (start + end)/2) // Legal +``` + +## Interactions with other syntax + +#### Partially Applied Functions: +It must be required to specify the default arguments if the default argument's reference is unapplied: +```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 = 0) // Illegal (need to declare end) +``` + +#### 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 +``` + +#### Referring to type members: +The default parameters should be able to refer to type members of other arguments e.g.: +```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) \ No newline at end of file From d665502a6a8556b42f8357ccd92ea5e92a7237cb Mon Sep 17 00:00:00 2001 From: Pathikrit Bhowmick Date: Wed, 11 Jan 2017 15:56:26 -0500 Subject: [PATCH 2/3] Update 2017-01-11-refer-other-arguments-in-args.md --- ...017-01-11-refer-other-arguments-in-args.md | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md index 6674c4be64..9648fab42f 100644 --- a/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md +++ b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md @@ -1,16 +1,17 @@ --- layout: sip disqus: true -title: SIP-NN - SIP Title +title: SIP-NN - Allow referring to other arguments in default parameters --- **By: Pathikrit Bhowmick** ## History -| Date | Version | -|---------------|---------------| -| Jan 11th 2017 | Initial Draft | +| Date | Version | +|---------------|------------------| +| Jan 11th 2017 | Initial Draft | +| Jan 12th 2017 | Initial Feedback | ## Introduction Currently there is no way to refer to other arguments in the default parameters list: @@ -27,6 +28,15 @@ def substring(s: String, start: Int = 0)(end: Int = s.length): String However, the above workaround is not always suitable in certain situations. +The other more verbose alternative is by overloading: + +```scala +def substring(s: String, start: Int = 0, end: Int = s.length): String + = substring(s, start = 0, end = s.length) +def substring(s: String, start: Int, end: Int): String +``` + + ### Proposal Allow to refer to ***any*** parameters in the same (or left) curried parameter list: ```scala @@ -44,7 +54,7 @@ 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*** paramaeters: +We should also be able to refer to ***multiple*** parameters: ```scala def binarySearch(start: Int, end: Int, middle: Int = (start + end)/2) // Legal ``` @@ -52,13 +62,13 @@ def binarySearch(start: Int, end: Int, middle: Int = (start + end)/2) // Legal ## Interactions with other syntax #### Partially Applied Functions: -It must be required to specify the default arguments if the default argument's reference is unapplied: +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 = 0) // Illegal (need to declare end) +substring(_, start = 5) // Legal (same as s => substring(s, start = 5, end = s.length) ``` #### Multiple Implicit Parameters @@ -87,4 +97,4 @@ The following languages allow referring to previously declared arguments in the 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) \ No newline at end of file +[Scala Lang Forum](https://contributors.scala-lang.org/t/refer-to-previous-argument-in-default-argument-list/215/6) From 04ba8c3359e87efcc1303c107ff0a3e56b2ed19f Mon Sep 17 00:00:00 2001 From: Pathikrit Bhowmick Date: Mon, 16 Jan 2017 17:01:31 -0500 Subject: [PATCH 3/3] Minor review suggestions --- .../2017-01-11-refer-other-arguments-in-args.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md index 9648fab42f..936d60ab63 100644 --- a/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md +++ b/sips/pending/_posts/2017-01-11-refer-other-arguments-in-args.md @@ -12,6 +12,7 @@ title: SIP-NN - Allow referring to other arguments in default parameters |---------------|------------------| | 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: @@ -26,16 +27,16 @@ The workaround to achieve this is by using a curried-function: def substring(s: String, start: Int = 0)(end: Int = s.length): String ``` -However, the above workaround is not always suitable in certain situations. +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 = 0, end: Int = s.length): String +def substring(s: String, start: Int): String = substring(s, start = 0, end = s.length) -def substring(s: String, start: Int, end: Int): String +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: @@ -59,6 +60,10 @@ We should also be able to refer to ***multiple*** parameters: def binarySearch(start: Int, end: Int, middle: Int = (start + end)/2) // Legal ``` +# Motivating examples: + +TBD + ## Interactions with other syntax #### Partially Applied Functions: