簡體   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