繁体   English   中英

对Scala枚举进行惰性计算?

[英]Lazy evaluation of Scala Enumerations?

考虑以下代码片段,按字母顺序排列从1到9的所有数字:

object AlphabetizedDigit extends Enumeration {
    type AlphabetizedDigit = Value
    val one, two, three, four, five, six, seven, eight, nine = Value
}

println(for(i <- Range(0, AlphabetizedDigit.maxId)) yield (i, AlphabetizedDigit(i)))

由于零索引, println的输出将有点不直观:

jason@debian:~/code/atomicscala$ scala EnumIDRange.scala 
Vector((0,one), (1,two), (2,three), (3,four), (4,five), (5,six), (6,seven), (7,eight), (8,nine))

解决此问题的一种方法是按以下方式更改AlphabetizedDigit成员的定义:

val one = Value(1)
val two, three, four, five, six, seven, eight, nine = Value

然后确保Range1而不是0开始。 这样的输出就是直观的输出:

jason@debian:~/code/atomicscala$ scala EnumIDRange.scala 
Vector((1,one), (2,two), (3,three), (4,four), (5,five), (6,six), (7,seven), (8,eight), (9,nine))

但是,我真的不喜欢这样的事实,如果只想切换枚举的起始索引,就需要将声明分成两行。 因此,我尝试了以下方法,它们可以正常编译:

val one, two, three, four, five, six, seven, eight, nine = Value(1)

但是,在运行时,由于使用了重复的ID,所以抛出了AssertionError 这在我看来很有意义,但是我很好奇为什么在运行时而不是编译时抛出此错误。

您可以使用Enumeration的第二个构造函数,例如:

object AlphabetizedDigit extends Enumeration(1) {
    type AlphabetizedDigit = Value
    val one, two, three, four, five, six, seven, eight, nine = Value
}

表格doc: new Enumeration(initial: Int)

如果查看Scala的Enumeration的源代码 ,则会看到以下内容:

/** The cache listing all values of this enumeration. */
@transient private var vset: ValueSet = null
@transient @volatile private var vsetDefined = false

和:

/** The values of this enumeration as a set.
 */
def values: ValueSet = {
  if (!vsetDefined) {
    vset = (ValueSet.newBuilder ++= vmap.values).result()
    vsetDefined = true
  }
  vset
}

因此,似乎直到需要才实际评估值集,因此该错误仅在运行时显示。 这看起来似乎是实现Enumeration一种糟糕方法,但是我通常更喜欢使用密封的特征以及案例类和对象,因此无论如何* shrug *都很少处理Enumeration

至于从0索引的问题,为什么不添加zero条目呢?

val zero, one, two, three, four, five, six, seven, eight, nine = Value

如果需要,您仍然可以从1开始计数:

scala> println(for(i <- Range(1, AlphabetizedDigit.maxId)) yield (i, AlphabetizedDigit(i)))
Vector((1,one), (2,two), (3,three), (4,four), (5,five), (6,six), (7,seven), (8,eight), (9,nine))

或仅从0开始计数并获得所有十位数:

println(for(i <- Range(0, AlphabetizedDigit.maxId)) yield (i, AlphabetizedDigit(i)))
Vector((0,zero), (1,one), (2,two), (3,three), (4,four), (5,five), (6,six), (7,seven), (8,eight), (9,nine))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM