scala-library-next
scala-library-next copied to clipboard
Proposals for naming and package structure
Proposals:
- Only names that are planned to exist in a future Scala release can be outside of a
next(sub-)package. Names that will not exist in a future Scala release MUST be in anext(sub-)package. a. Corollary: Extension methods MUST go innext(sub-)packages. b. Possible extension: All names that are planned to exist in a future Scala release MUST be outside ofnext(sub-)packages. - Extension method value classes SHOULD be named
Next<Name>Extensions, where<Name>is the name of the type. a. For example, extension methods forLazyListwould go in value class namedNextLazyListExtensions. b. Extension method value classes for an object that is a companion SHOULD be namedNext<Name>CompanionExtensions. c. Extension method value classes for general collection types (e.g.Map,Set) should have have a prefix to<Name>that is the first letter of each package segment (e.g.NextSCISetExtensionsforscala.collection.immutable.Set)
Something something RFC 2119
Names that will not exist in a future Scala release MUST NOT be outside of a next (sub-)package.
The triple negation was very hard for me too read, and I understood it the wrong way the first two times I read the sentence. Perhaps consider:
-Names that will not exist in a future Scala release MUST NOT be outside of a next (sub-)package.
+Names that will not exist in a future Scala release MUST be inside of a next (sub-)package.
I don't know why that slipped by me. yes, fixed
@NthPortal How should the object holding the value class be named? Just <Name>Extensions?
So for example, if I want some additional methods on LazyList I would import scala.collection.immutable.next.LazyListExtensions._?
IMO, it can go directly in the package object.
@NthPortal so importing next._ would import all extensions?
correct. and if you wanted to import just one, you'd import next.NextLazyListExtensions or whatever
Having to import next.something would mean that cross-building 3.0/3.1 won't be possible unless we ship this with empty next instances for 3.1. that'd be lame.
then just import next._
would -Yimports:... be helpful here, when cross-building? as a way of allowing the imports to be different in different Scala versions, as needed, without the user having to alter their actual source code? (cc @som-snytt)
Then you'd still need to ship a version with an empty next package for 3.1. which means inflicting the transitive dependency on your dependents.
That can be sort of worked around with people taking a provided dependency for 3.1.
Having to import next.something would mean that cross-building 3.0/3.1 won't be possible unless we ship this with empty next instances for 3.1. that'd be lame.
I think that shipping empty next instances is exactly what we'll do.
Anyway, they probably won't stay empty as we then start adding new stuff coming in 3.2 or later.
Julien suggested on https://github.com/scala/scala-library-next/issues/25 that there wouldn't be 3.2 stuff in this library.
Per version -Yimports is probably at least as invasive/cumbersome for users as having the lame dependency on the empty next package and declaring it provided for 3.1.
I've noticed we still have a shadowing problem for names which appear in multiple packages (e.g. Set, Seq), so I've updated the proposals to account for that
Did you come to a conclusion about this?
So I could update #23 and open a follow up for groupByTo & groupMapTo
Vote by reacting to this comment (see the following comment for more granular votes)
In favour of (👍) or against (👎) proposal 1 in its entirety
In favour of (🚀) or agains (👀) proposal 2 in its entirety
Granular votes (by reacting):
In favour of proposals 1 and 1a but against 1b (👀) In favour of proposals 2 and 2a but against 2b (👎) In favour of proposals 2 and 2a but against 2c (😕)
This all looks good, except I don't know what I think about 1b. What are the pros and cons there?
I'll give an example of something that 1b affects.
Currently, scala.collection.concurrent.Map does not have a companion, unlike other Map types (see scala/bug#12115). We cannot add it in that package in scala-library-next, because the companion needs to be in the same compilation unit. If we were to add such a companion, it would have to be an object Map in package scala.collection.concurrent.next; however, that would violate 1b.
If we were to reject 1b and add s.c.c.next.Map, we would need an alias val Map = s.c.c.Map in package s.c.c.next in the Scala 3.1 version of this library, and couldn't just have an empty package.
As I see it,
Pros: simplicity
Cons: reduces the total set of possible changes/fixes/improvements
the current proposals only take into consideration the naming of the implicit value classes, but [do] not define where they should be defined.
These proposals also make some constraints on what MUST go in a next (sub-)package, and perhaps what MUST NOT as well.
As I said before, I do not [...] think that having all of them in the
package objectto be a good idea, the file will be pretty big and searching for the implementation of a particular method would be difficult.
By all means feel free to create a proposal that specifies that. These proposals were not intended to specify everything that needs to be decided about the library's structure.
It's worth noting that value classes MUST live inside (top-level) objects, so having them split up necessitates a separate wrapper object for each extension method value class.
Only names that are planned to exist in a future Scala release can be outside of a next (sub-)package. Names that will not exist in a future Scala release MUST be in a next (sub-)package.
AFAIK the idea is that if something will not exist in a future scala version (or it is still not clear if it should be part or not of) then it shouldn't be here in the first place.
I was very deliberate with my wording. Names that will not exist in a future Scala version have to be in a next (sub-)package. For example, since 3.1 will not have the name NextLazyListExtensions, that value class/extension MUST be in a next (sub-)package. I said "names", not "things".
The reason 1a is a corollary is because, at least using Scala 2 syntax, extension methods require a value class and an implicit conversion to it (which are usually combined as in an implicit value class), both of which are names that are not intended to exist in a future Scala version. Thus, they MUST be in next (sub-)packages.
a. Corollary: Extension methods MUST go in next (sub-)packages.
I would also add this to the second proposal.
Proposal 1 is about package structure; proposal 2 is about the naming of value classes for extension methods. That's why 1a is where it is. Additionally, 1 strictly implies 1a; they are inseparable.
Also, I'm not sure why a particular item should be proposed twice.
Isn't that what I did here and that I repeated here
I meant a separate issue/ticket
// file: src/main/scala/scala/next/Next<Name>Extensions.scala package scala.next private[next] final class Next<Name>Ops[A](private val col: <Name>[A]) extends AnyVal { // Extension methods go here. }
Scala 2 does not permit top-level value classes
I meant a separate issue/ticket
Isn't this issue for all the proposals and choosing one?
Scala 2 does not permit top-level value classes
Ham yes it does, you are confusing it with implicit classes, that is why the implicit conversion is in the package object. This is a simplified version of what libraries like cats or neotypes do.
yes it does, you are confusing it with implicit classes
you're right, my mistake
Isn't this issue for all the proposals and choosing one?
no. it's an issue for the 2 proposals (and their sub-proposals/extensions) listed in the issue description. also, again, the proposals in this issue's description are not options, one of which gets chosen. they are two independent proposals, each to be accepted or rejected individually.
I meant a separate issue/ticket
Done #46
no. it's an issue for the 2 proposals (and their sub-proposals/extensions) listed in the issue description. also, again, the proposals in this issue's description are not options, one of which gets chosen. they are two independent proposals, each to be accepted or rejected individually.
Yeah yeah, my point was that my proposal was also complementary with yours, so I thought it made sense to be in the same issue, but ok.
I also deleted all my comments in this issue that I believe are no longer relevant.
follow-up at #46
I propose that we don't wait on finalizing this and #46 to merge PRs, and we can just refactor the library once we've decided on those.