enumeratum
enumeratum copied to clipboard
Scala 3: What should be done
Looking at Scala 3, the enumerations built into the language look pretty good.
The questions are
- What should
enumeratum
look like in a Scala 3 world?- What problems are we trying to solve? The problems with Scala 2 enums were pretty obvious, which led to the core of this lib
The first step towards Scala 3 for any real-world project is cross-compilation between Scala 2.13/Scala 3. Most of the OSS libs added Scala 3 to their cross-builds.
IMO, this will be a status quo for the next few years. Only then we'll drop Scala 2 support and migrate to the new enums.
Thus, the Enumeratum macros should be ported.
My 2c: we use Enumeratum mostly to model things that map to postgres enums, with a nice benefit of being able to have safe withName*
overloads for decoding.
I'm not sure if Scala 3 enums has support for this...
The first step towards Scala 3 for any real-world project is cross-compilation between Scala 2.13/Scala 3. Most of the OSS libs added Scala 3 to their cross-builds.
IMO, this will be a status quo for the next few years. Only then we'll drop Scala 2 support and migrate to the new enums.
Thus, the Enumeratum macros should be ported.
Fair point; have you checked that the macro(s) in its current form can be ported? A PR would be welcome to start concrete discussions as well.
My 2c: we use Enumeratum mostly to model things that map to postgres enums, with a nice benefit of being able to have safe
withName*
overloads for decoding.I'm not sure if Scala 3 enums has support for this...
~I think there is a way of having custom names, based on this doc https://github.com/dotty-staging/dotty/blob/master/docs/docs/reference/enums/desugarEnums.md#translation-of-enums-with-singleton-cases~
Nevermind... looks like support for custom enumLabel
was added, then later removed, and I can't figure out how to get it working (Scastie attempts)
@lloydmeta I think you were looking for valueOf
: scastie session
@note Hmmm I think that's almost it, but how do we make the second print resolve Red
from the custom name "red"
?
@lloydmeta Ah, I missed the point that it's about custom names as I mostly looked at scastie session using outdated ofValue
. I am not sure about support for custom names in Scala 3 as well
Thus, the Enumeratum macros should be ported.
any plan to have the macros ported?
Thus, the Enumeratum macros should be ported.
any plan to have the macros ported?
The plan is:
- Come up with a working prototype for the macro, either on Scastie or a PR
- In particular, the
enclosingModule
function is basically gone with no replacement in Scala 3 AFAIK, so we can't explore inside a "scope" forfindValues
https://github.com/lloydmeta/enumeratum/blob/dddab99216fed3b5443d4698893dfc1f4877e7c1/macros/src/main/scala/enumeratum/EnumMacros.scala#L79-L95
- In particular, the
- Implement the prototype.
Currently stuck on (1).
In particular, the enclosingModule function is basically gone with no replacement in Scala 3 AFAIK
There is some dotty/scala3 issue about that?
Alternatively, could we change the signature of findValues
so we can pass that enclosingModule
, like:
sealed abstract class Light extends EnumEntry
case object Light extends Enum[Light] {
val values = findValues[Light]
case object Red extends Light
case object Blue extends Light
case object Green extends Light
}
Sorry if this, does not make sense at all, because I am not very familiar with macros...
In particular, the enclosingModule function is basically gone with no replacement in Scala 3 AFAIK
There is some dotty/scala3 issue about that?
Nope. I think it was a conscious decision/redesign around the Scala 3 macro system.
Alternatively, could we change the signature of
findValues
so we can pass thatenclosingModule
, like:sealed abstract class Light extends EnumEntry case object Light extends Enum[Light] { val values = findValues[Light] case object Red extends Light case object Blue extends Light case object Green extends Light }
It's not so much a problem of having to provide the type param (the compiler can figure that out in the same way I think), just AFAICT, the functionality to explore the object
scope is gone.
I think one way might be to change it into something that works on a defined scope like so, but it's not backwards-source compatible.
sealed abstract class Light extends EnumEntry
@findEnumValues // or find members at this point
case object Light extends Enum[Light] {
case object Red extends Light
case object Blue extends Light
case object Green extends Light
}
To be clear: the only helpful next step in this issue is for someone to come forth with a working prototype.
Actually it's possible to access "enclosingModule" via Symbol.spliceOwner.owner...owner
.
Here is a prototype: Scastie
@marq Thanks so much for that (even including a Scastie!). I'm very unfamiliar with the new Scala 3 macros (and it seems like the documentation may not be the most complete ?) so I'm having a hard time and would really appreciate the help of those who are such as yourself 🙏🏼
To provide a clean sandbox to hack around, I created a separate repo to explore porting macros to Scala 3 some more, and split it into 3 issues, one for each main macro method:
https://github.com/lloydmeta/mune/issues
Since you've done most of the work, https://github.com/lloydmeta/mune/issues/1 is basically done, but I'm running into some errors on https://github.com/lloydmeta/mune/issues/2 (materialising the companion object of an enum entry type); wondering you can spot anything wrong there. https://github.com/lloydmeta/mune/issues/3 is also a TODO.
Hi @lloydmeta ! It seems that enumeratum still provides stuff that native scala3 enums don't, does it? Would be great to have I guess. Are you actively working on that?
Hi @lloydmeta ! It seems that enumeratum still provides stuff that native scala3 enums don't, does it? Would be great to have I guess. Are you actively working on that?
Hey there @mauhiz , yeah, it turns out there are some things missing from the official Scala 3 enums that is supported here. I agree it would be nice to have, but I got stuck in my attempt to port the macro to Scala3 (see https://github.com/lloydmeta/enumeratum/issues/300#issuecomment-885486518). I'm not actively working on it and any help would be appreciated :)
Thanks to @tpunder, the Scala 3 port is mostly complete.
The remaining bit is https://github.com/lloydmeta/mune/issues/3, which involves porting over this bit
https://github.com/lloydmeta/enumeratum/blob/d91d191cd11a630cc4d1b7cc6c82decdf436ac1b/macros/src/main/scala/enumeratum/ValueEnumMacros.scala#L85-L117
I think the main tricky bit is finding how to destructure the different ways to declare value
in a Scala 3 world.
@lloydmeta this might be helpful: https://github.com/theiterators/kebs/blob/master/macro-utils/src/main/scala-3/pl/iterators/kebs/macros/enums/EnumEntryMacros.scala
@lloydmeta any update on this? Thanks
There's a PR open (https://github.com/lloydmeta/enumeratum/pull/349) that I've slowly been reviewing over iterations.
Done.
First off, thank you.
Second, I notice that there are two separate libraries: one for scala 3 and one for scala 2. Is there any plan or desire to have a mixed library that can be used in scala 3 and in scala 2? This would be useful for large projects that use enumeratum that want to migrate to scala 3 gradually. I think the alternatives would be either migrating all at once, or depending on both libraries, and I don't know how well depending on both libraries would work out in practice (I imagine not well)
Is there any plan or desire to have a mixed library that can be used in scala 3 and in scala 2
There's no plan, but it does sound desirable; do you want to give it a stab ?
Sure, I'll take a stab at it
I have something that I think would work, but there's a bug in the macro mixing functionality that is triggered by using type parameters from the class level in a scala 2 macro call. So I don't think any further progress can be made until that's fixed.
branch: https://github.com/lloydmeta/enumeratum/compare/master...lucidsoftware:enumeratum:mix-scala-2-and-3-macros scala bug: https://github.com/lampepfl/dotty/issues/16630