I just ran the following Scala 3 code in Scastie (which blows up Scastie if 3.0.2 is selected, but works if 3.1.0-RC1 is selected) which uses a var
(not a val
) to define the rgb attribute.
Is this supposed to compile? IOW, why aren’t all the attributes to an enum forced to be a val
?
enum Color(var rgb: Int):
case Red extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue extends Color(0x0000FF)
val c = Color.Red
println(c)
println(c.rgb)
println("----------")
c.rgb = 0x00FF00
println(c)
println(c.rgb)
This is similar to the discussion if case classes should allow var-parameters and other var-members or not. I guess it is reasonable to argue by regularity that, as the enum type expands to an abstract class, and you actually need to write modifiers like val
or var
or private val
etc for enum params, then any such relevant modifier should be allowed.
If one argues otherwise, that it should be a deliberate restriction to only allow val-parameters and val-members in enums, then perhaps you shouldn’t even have to write val
at all as with case-classes. But still enums would then be irregular wrt case classes, as the latter do allow mutable parameters and other mutable members.
Note that a parameter is a “special case” of a member that is initialized during construction, so creating mutable enums would still be possible e.g. by including var-members (as with case classes etc), (assuming no hypothetical restriction on var-members in enums, not even private var):
scala> enum Mutant:
| var x: Int = 0
| case Red, Green
|
// defined class Mutant
scala> val x = Mutant.Red
val x: Mutant = Red
scala> x.x = 42
scala> x.x
val res0: Int = 42
More general, this is a choice of pragmatism or purism and Scala tends to go with the former. I think the behaviour of 3.1.0-RC1 makes sense given how enums are expanded:
https://docs.scala-lang.org/scala3/reference/enums/desugarEnums.html
1 Like
Very likely, as Scala 3 continues to gain popularity, we’ll start to see linters that can flag such things. At least, they existed in Scala 2 (for instance, WartRemover). Very likely these would be in the form of scalafix lints, but currently, Scala 3 still lacks some facilities to make it easy for scalafix to do what it needs.
1 Like