Is it possible to define a new method for a member of an enum in Scala3? (Not every member - just one member.)
I tried
enum E:
case B extends E()
def b() = "b"
And killed the REPL with
casException in thread "main" java.lang.AssertionError: assertion failed:
dotty.tools.dotc.parsing.Scanners$$anon$1@1fe8f5e8
at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
at dotty.tools.dotc.parsing.Scanners$Scanner.insert(Scanners.scala:360)
at dotty.tools.dotc.parsing.Scanners$Scanner.observeOutdented(Scanners.scala:586)
at dotty.tools.dotc.parsing.Parsers$Parser.acceptStatSepUnlessAtEnd(Parsers.scala:327)
While this code compiles, it doesn’t define a member just for B despite the indentation, it defines a member in E. There is intentionally no way to define a member for just a case of an enum, since the case type usually gets widened to the enum type.
I’ve found it really useful to have a list of case objects that all implement a sealed trait in Scala 2. I give case objects their own methods as needed. I was hoping to replace that pattern with Scala 3 enums - to be less pattern-y, and to have less to explain to the kids.
I didn’t expect to find a Scala 3 puzzler this early. Thanks!
Uhm, not sure how to answer that.
Is like asking why 1 + 2 returns the sum of the two numbers instead of the multiplication.
Is just what the designers chose.
Maybe I may say that such is the most common case; at least in my experience.
To extend the arithmetic example, what I’d hoped for was something that would let me have an enumeration of operations. Add, Subtract, and Multiply are all pretty simple, with the same shape. Divide could implement all the odd code that expresses what a mess division is. With a Java-style enum the special mess of Divide has to be held elsewhere.
For my case: I’ve got a set of sensor modes that work with a single sensor. The modes have specific methods to interpret the same raw signal. I’d like to use an enum because it’s easier to explain than that pattern.
Can an enum take a function as a parameter? I have to explain higher-order functions already. That could be interesting. (That still wouldn’t give an extra named method to the enum.)
Each physical sensor plugged into the brick shows up as a directory in /sys/class/lego-sensor . I use an outer class to represent each sensor on the robot - Ev3ColorSensor . Every time the sensor is (unplugged and) plugged back in then a new directory appears. I use a new object to read and write to that new directory for every plug-in. Every kind of sensor has multiple modes; the mode determines how the files in the directory should be interpreted. There are several sensors of interest, with several modes each. Modeling them as case objects or case classes that extend a common trait - using the pattern for enums I used in scala 2 - feels like a lot of boilerplate.
Modes for the Ev3ColorSensor are ReflectedColor, AmbientColor, DefinedColor (one of eight colors), RawReference, RawRgb, and Calibrate . I’d like to represent the modes as an enum - because the modes are a bound set of immutable things. I want the students to be able to only use methods for each mode that make sense: I’d like for a red():Int, green():Int, and blue():Int method to only exist on RawRgb, and a color():Color method to return one of the 8 colors only to exist in DefinedColor mode.
I want to introduce enums early, and inheritance later. But I’d have to do a feature request to get that in Scala 3. And that’d carry Scala past the Java enum limitations. I think that’s the boundary in Scala3.
In your example, I really don’t see the value of the abstraction at all; what is the point of having Operator and it being sealed?
It is not an ADT since it is not holding data, and is not a traditional OOP interface because the root type doesn’t provide anything of value at all.
My general advice would be to separate data from logic.
So the idea would be that the enum cases are just plain objects / classes, and there is an interpreter which does things according to the data inside the ADT. That way you don’t need to have special methods inside each case. - Or, just go the traditional OOP route of having an open interface.
I just saw a video on “enum” and they create an enum type, but then they added a method within the enum. I don’t understand that. Why is it allowed?
If you create a trait with an enum or opaque type and a method (abstract or not), you would use it with a companion object or extending it into an object or class. How would you use an enum with a method?