如何使用宏来创建简洁,类型安全,非箱化的枚举?
如何使用宏来创建简洁,类型安全,非箱化的枚举?
我正在学习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个可选值的枚举表示为位,并具有高效的未装箱实现其设置(作为Int
或Long
)。
拥有此类内容的另一个令人信服的原因是,我们还可以自定义稍有不同的enum
风格的不同方面,例如,在上述代码中,我们可以为enum
提供一些参数,以便next
集合中循环,而不会在Sunday
上出错。
admin 更改状态以发布 2023年5月21日
因此,根据Rex Kerr 的回答,我发现需要查看StaticAnnotation
,然后在这里制作了一个简单实现。 对于我的个人用途,我不认为有必要与Java保持良好的互操作性,但我仍然这么做了。
(请允许我无耻地接受自己的答案^^)
这项工作已经尝试过了(由Alois Cochard和Simon Ochsenreither进行),这样做是与Java枚举兼容的,但是我记得Scala编译器没有向字节码中发出一些所需的标志,而且这个项目陷入了困境。我知道的最新版本在这里。
我不确定它对你的想法是否有用。你需要为语法努力工作,因为我不确定是否能解析,而且你可能需要一些高级的宏的风格(例如Scala Meta)来完成它。