Access to enum ADT ordinal in absence of case instance

Let us have the following enum definition.

 enum Events:
   case First
   case Second
   case HanderReceived(value: Int)

When using this code, we can write First.ordinal, Second.ordinal but not HandlerReceived.ordinal, because ordinal is a method of case instance.

Proposal: add an ordinal method to the companion objects of enums ADT to receive ability call method ordinal without instantiation of case instance.

It is helpful when we want to index something by possible ordinals.

Example:
Let us have some processing engine with those events and keep somewhere in our program Map[Int, Event] for the last coming events.

var lastEvents: Map[Int, Event] = Map.empty

When we receive an event, we can update this map:

lastEvent = lastEvent.updated(event.ordinal, event)

But we can’t look - are we receive HandlerRecieved:

lastEvent.get(HandlerReceived.ordinal) // error now: value ordinal is not a member of Event.HandlerReceived , but could be made available as an extension method.

Adding ordinal alias to Event.HandlerReceived will make the situation more pleasant.

1 Like

Btw, dotty-feature-request for this already exists: https://github.com/lampepfl/dotty-feature-requests/issues/200

You can already implement this functionality with the help of scala.deriving.Mirror, which can reflect on the ordinals of enum types.

In 3.0.2 you should be able to write the following:

import compiletime.ops.int.+
import compiletime.constValue
import deriving.Mirror

inline def ordinalOf[E, C <: E](using me: Mirror.SumOf[E]): Int =
  constValue[SearchElem[me.MirroredElemTypes, C, 0]]

type SearchElem[T <: Tuple, X, N <: Int] <: Int = T match
  case X *: _  => N
  case _ *: xs => SearchElem[xs, X, N + 1]

and here i use it with Events:

enum Events:
  case First
  case Second
  case HanderReceived(value: Int)

val ordFirst: Int           = ordinalOf[Events, Events.First.type]
val ordSecond: Int          = ordinalOf[Events, Events.Second.type]
val ordHandlerRecieved: Int = ordinalOf[Events, Events.HanderReceived]

This could be improved if we could have a way to summon the mirror of the parent of an enum case, so you would only need to pass Events.HandlerRecieved

5 Likes

Thanks, … from the usability point of view, I still expect to have original in ADT companion object will be practically worth having. [ why – I accidentally wrote a block of code, thinking that this functionality exists. I guess that my application programmer intuition is more or less the same as average, so others will be come to the same logic]. So, feature is ‘nice to have’.