For a project of mine I have implemented a Enum based upon
trait Enum[A] {
trait Value { self: A =>
_values :+= this
}
private var _values = Li
The article "“You don’t need a macro” Except when you do" by Max Afonov maxaf describes a nice way to use macro for defining enums.
The end-result of that implementation is visible in github.com/maxaf/numerato
Simply create a plain class, annotate it with
@enum
, and use the familiarval ... = Value
declaration to define a few enum values.The
@enum
annotation invokes a macro, which will:
- Replace your
Status
class with asealed Status
class suitable for acting as a base type for enum values. Specifically, it'll grow a(val index: Int, val name: String)
constructor. These parameters will be supplied by the macro, so you don't have to worry about it.- Generate a
Status
companion object, which will contain most of the pieces that now makeStatus
an enumeration. This includes a values:List[Status]
, plus lookup methods.Give the above
Status enum
, here's what the generated code looks like:
scala> @enum(debug = true) class Status {
| val Enabled, Disabled = Value
| }
{
sealed abstract class Status(val index: Int, val name: String)(implicit sealant: Status.Sealant);
object Status {
@scala.annotation.implicitNotFound(msg = "Enum types annotated with ".+("@enum can not be extended directly. To add another value to the enum, ").+("please adjust your `def ... = Value` declaration.")) sealed abstract protected class Sealant;
implicit protected object Sealant extends Sealant;
case object Enabled extends Status(0, "Enabled") with scala.Product with scala.Serializable;
case object Disabled extends Status(1, "Disabled") with scala.Product with scala.Serializable;
val values: List[Status] = List(Enabled, Disabled);
val fromIndex: _root_.scala.Function1[Int, Status] = Map(Enabled.index.->(Enabled), Disabled.index.->(Disabled));
val fromName: _root_.scala.Function1[String, Status] = Map(Enabled.name.->(Enabled), Disabled.name.->(Disabled));
def switch[A](pf: PartialFunction[Status, A]): _root_.scala.Function1[Status, A] = macro numerato.SwitchMacros.switch_impl[Status, A]
};
()
}
defined class Status
defined object Status