From ebe6ba66788384e1884c1bf5d2b38548dce91848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Thu, 21 Apr 2016 21:50:21 +0200 Subject: [PATCH 1/5] Initial draft for multiple implicit parameter lists SIP --- ...04-21-multiple-implicit-parameter-lists.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md diff --git a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md new file mode 100644 index 0000000000..101efad38e --- /dev/null +++ b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md @@ -0,0 +1,66 @@ +--- +layout: sip +disqus: true +title: SIP-NN - SIP Allow multiple implicit parameter lists +--- + +**By: Miles Sabin and Merlin Göttlinger** + +## History + +| Date | Version | +|---------------|---------------| +| Apr 21st 2016 | Initial Draft | + +## Motivation + +In Scala the implicit parameters of a function are limited to being placed in the single very last parameter list of a function. This prevents later parameters from using dependant types of former ones as this is only allowed between, but not inside a single parameter list. Another issue introduced by this restriction is, that if you want to explicitly specify one of the implicit parameters you have to specify all of them by hand (or write `implicitly` in place of every other parameter that should be filled by the compiler). + +## Motivating Examples + +### Examples + +For regular parameter lists it is possible to write the following: +{% highlight scala %} +trait A { type B } + +def works(a: A)(b: a.B) = "works" +{% endhighlight %} +Due to the restriction of being contained in a single parameter list the implicits can't benefit from this goodness. A common workaround is to pull the type member `B` into a type parameter of a new `Aux` object and having this as a type parameter of your function: +{% highlight scala %} +trait A { type B } +object A { type Aux[D] = A { type B = D } } + +def works[B](implicit a: A.Aux[B], b: B) = "works" +{% endhighlight %} +While this works it introduces unnecessary complexity because our method shouldn't need to have type parameters and we shouldn't need the `Aux` object just to use the type member of `A` for implicits. + +With the proposed change of allowing multiple implicit parameter lists the example would again be reduced to the following concise and readable example: +{% highlight scala %} +trait A { type B } + +def worksWithImplicits(implicit a: A)(b: a.B) = "pls make me work" +{% endhighlight %} + +Another benefit mentioned before would be that implicit parameters, that are expected to often be filled in manually can be put in separate lists. +{% highlight scala %} +def now(implicit a: Int, b: String) = b * a +now(1, implicitly) + +def then(implicit a: Int)(b: String) = b * a +then(1) +{% endhighlight %} + +## Implementation + +The implementation of this change is as simple as removing the artificial restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions. + +## Drawbacks + +The current simple implementation may not make it obvious from first glance that parameter lists coming after a implicit list are also implicit. + +## References + +1. [Miles' PR][1] + +[1]: https://github.com/scala/scala/pull/5108 "PR#5108" From 00cd6643f74cc7df5b312b14a27ef645405f4383 Mon Sep 17 00:00:00 2001 From: Phil Wills Date: Thu, 21 Apr 2016 21:46:55 +0100 Subject: [PATCH 2/5] Minor edits for clarity --- .../2016-04-21-multiple-implicit-parameter-lists.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md index 101efad38e..2c068d8844 100644 --- a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md +++ b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md @@ -14,7 +14,9 @@ title: SIP-NN - SIP Allow multiple implicit parameter lists ## Motivation -In Scala the implicit parameters of a function are limited to being placed in the single very last parameter list of a function. This prevents later parameters from using dependant types of former ones as this is only allowed between, but not inside a single parameter list. Another issue introduced by this restriction is, that if you want to explicitly specify one of the implicit parameters you have to specify all of them by hand (or write `implicitly` in place of every other parameter that should be filled by the compiler). +Currently, the implicit parameters of a function are limited to being placed in a single, final, parameter list of a function. This prevents later parameters from using dependant types of former ones, as this is only allowed between, but not inside a single parameter list. + +This restriction also means that if you want to explicitly specify one of the implicit parameters you have to specify all of them by hand (or write `implicitly` in place of every other parameter that should be filled by the compiler). ## Motivating Examples @@ -26,7 +28,7 @@ trait A { type B } def works(a: A)(b: a.B) = "works" {% endhighlight %} -Due to the restriction of being contained in a single parameter list the implicits can't benefit from this goodness. A common workaround is to pull the type member `B` into a type parameter of a new `Aux` object and having this as a type parameter of your function: +Due to the restriction of being contained in a single parameter list, implicit parameters can't work in the same way. A common workaround is to pull the type member `B` into a type parameter of a new `Aux` object and make this a type parameter of your function: {% highlight scala %} trait A { type B } object A { type Aux[D] = A { type B = D } } @@ -53,7 +55,7 @@ then(1) ## Implementation -The implementation of this change is as simple as removing the artificial restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions. +The implementation of this change is as simple as removing the restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions. ## Drawbacks From e4e08a8fb3734d9fc992a7cf2a48ede9c54cfe14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Fri, 22 Apr 2016 10:39:38 +0200 Subject: [PATCH 3/5] implicit keyword in every implicit list --- .../2016-04-21-multiple-implicit-parameter-lists.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md index 2c068d8844..ec2f34fd6b 100644 --- a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md +++ b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md @@ -41,7 +41,7 @@ With the proposed change of allowing multiple implicit parameter lists the examp {% highlight scala %} trait A { type B } -def worksWithImplicits(implicit a: A)(b: a.B) = "pls make me work" +def worksWithImplicits(implicit a: A)(implicit b: a.B) = "pls make me work" {% endhighlight %} Another benefit mentioned before would be that implicit parameters, that are expected to often be filled in manually can be put in separate lists. @@ -49,17 +49,14 @@ Another benefit mentioned before would be that implicit parameters, that are exp def now(implicit a: Int, b: String) = b * a now(1, implicitly) -def then(implicit a: Int)(b: String) = b * a +def then(implicit a: Int)(implicit b: String) = b * a then(1) {% endhighlight %} ## Implementation The implementation of this change is as simple as removing the restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions. - -## Drawbacks - -The current simple implementation may not make it obvious from first glance that parameter lists coming after a implicit list are also implicit. +The desugaring ob context and view bounds will be added on the left of the leftmost implicit parameter list to go with the general expectation from the current implementation. ## References From b486dfd7f51e8ad8a8e47efd05bc3bd1fe7cacd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Fri, 22 Apr 2016 15:31:35 +0200 Subject: [PATCH 4/5] Fixed typos --- .../_posts/2016-04-21-multiple-implicit-parameter-lists.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md index ec2f34fd6b..301e80a982 100644 --- a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md +++ b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md @@ -14,7 +14,7 @@ title: SIP-NN - SIP Allow multiple implicit parameter lists ## Motivation -Currently, the implicit parameters of a function are limited to being placed in a single, final, parameter list of a function. This prevents later parameters from using dependant types of former ones, as this is only allowed between, but not inside a single parameter list. +Currently, the implicit parameters of a function are limited to being placed in a single, final, parameter list of a function. This prevents later parameters from using dependent types of former ones, as this is only allowed between, but not inside a single parameter list. This restriction also means that if you want to explicitly specify one of the implicit parameters you have to specify all of them by hand (or write `implicitly` in place of every other parameter that should be filled by the compiler). @@ -56,7 +56,7 @@ then(1) ## Implementation The implementation of this change is as simple as removing the restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions. -The desugaring ob context and view bounds will be added on the left of the leftmost implicit parameter list to go with the general expectation from the current implementation. +The desugaring of context and view bounds will be added on the left of the leftmost implicit parameter list to go with the general expectation from the current implementation. ## References From 538aa0de4562b29003935634255abc5d7235eed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20G=C3=B6ttlinger?= Date: Sat, 23 Apr 2016 12:08:10 +0200 Subject: [PATCH 5/5] Added reference to Travis' blogpost as recommended by Jason --- .../_posts/2016-04-21-multiple-implicit-parameter-lists.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md index 301e80a982..600176047f 100644 --- a/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md +++ b/sips/pending/_posts/2016-04-21-multiple-implicit-parameter-lists.md @@ -61,5 +61,7 @@ The desugaring of context and view bounds will be added on the left of the leftm ## References 1. [Miles' PR][1] +2. [Travis' blogpost describing the issue a workaround][2] [1]: https://github.com/scala/scala/pull/5108 "PR#5108" +[2]: https://meta.plasm.us/posts/2015/07/11/roll-your-own-scala/ "Metaplasm: Roll-your-own Scala"