Custom Scala enum, most elegant version searched

后端 未结 3 2117
借酒劲吻你
借酒劲吻你 2020-12-16 17:26

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         


        
3条回答
  •  温柔的废话
    2020-12-16 18:00

    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 familiar val ... = Value declaration to define a few enum values.

    The @enum annotation invokes a macro, which will:

    • Replace your Status class with a sealed 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 make Status 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
    

提交回复
热议问题