如何使用宏来创建简洁,类型安全,非箱化的枚举?

21 浏览
0 Comments

如何使用宏来创建简洁,类型安全,非箱化的枚举?

我正在学习Scala宏,把它当做一种练习。

使用Scala宏,能否编写出类似以下内容的代码(也许不是一模一样的具体语法,但是没有样板文件的内容)

enum DayOfWeek = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday

并将它展开成以下内容?

class DayOfWeek private (val ord: Int) extends AnyVal {
  def next: DayOfWeek = ord match {
    case 0 => Tuesday
    case 1 => Wednesday
    case 2 => Thursday
    case 3 => Friday
    case 4 => Saturday
    case 5 => Sunday
    case _ => throw Error("Sunday does not have next")
  }
  override def toString: String = ord match {
    case 0 => "Monday"
    case 1 => "Tuesday"
    case 2 => "Wednesday"
    case 3 => "Thursday"
    case 4 => "Friday"
    case 5 => "Saturday"
    case _ => "Sunday"
  }
}
object DayOfWeek {
  def count = 7
  val Monday    = new DayOfWeek(0)
  val Tuesday   = new DayOfWeek(1)
  val Wednesday = new DayOfWeek(2)
  val Thursday  = new DayOfWeek(3)
  val Friday    = new DayOfWeek(4)
  val Saturday  = new DayOfWeek(5)
  val Sunday    = new DayOfWeek(6)
}

也许不一定需要使用连续整数来表示枚举。例如,通过一些标志,我们可以将不超过32或64个可选值的枚举表示为位,并具有高效的未装箱实现其设置(作为IntLong)。

拥有此类内容的另一个令人信服的原因是,我们还可以自定义稍有不同的enum风格的不同方面,例如,在上述代码中,我们可以为enum提供一些参数,以便next集合中循环,而不会在Sunday上出错。

admin 更改状态以发布 2023年5月21日
0
0 Comments

因此,根据Rex Kerr 回答,我发现需要查看StaticAnnotation,然后在这里制作了一个简单实现。 对于我的个人用途,我不认为有必要与Java保持良好的互操作性,但我仍然这么做了。

(请允许我无耻地接受自己的答案^^)

0
0 Comments

这项工作已经尝试过了(由Alois Cochard和Simon Ochsenreither进行),这样做是与Java枚举兼容的,但是我记得Scala编译器没有向字节码中发出一些所需的标志,而且这个项目陷入了困境。我知道的最新版本在这里

我不确定它对你的想法是否有用。你需要为语法努力工作,因为我不确定是否能解析,而且你可能需要一些高级的宏的风格(例如Scala Meta)来完成它。

0