【发布时间】:2013-07-24 14:16:47
【问题描述】:
我正在编写一个 Scala 程序,其中有一个创建序列的操作。该操作可能会失败,因此我将其包含在 Try 中。我想在 for 理解中进行序列创建和枚举,以便成功创建的序列产生一个元组序列,其中第一个元素是序列,第二个是它的元素。
为了简化问题,将我的序列设为整数的Range,并定义一个createRange 函数,如果要求创建一个奇数长度的范围,该函数将失败。这是一个简单的理解,可以满足我的要求。
import scala.util.Try
def createRange(n: Int): Try[Range] = {
Try {
if (n % 2 == 1) throw new Exception
else Range(0, n)
}
}
def rangeElements(n: Int) {
for {
r <- createRange(n)
x <- r
} println(s"$r\t$x")
}
def main(args: Array[String]) {
println("Range length 3")
rangeElements(3)
println("Range length 4")
rangeElements(4)
}
如果你运行它,它会正确打印。
Range length 3
Range length 4
Range(0, 1, 2, 3) 0
Range(0, 1, 2, 3) 1
Range(0, 1, 2, 3) 2
Range(0, 1, 2, 3) 3
现在我想重写我的rangeElements 函数,以便它返回一个整数序列,而不是作为副作用打印,如果未创建范围,则该序列为空。我要写的是这个。
def rangeElements(n: Int):Seq[(Range,Int)] = {
for {
r <- createRange(n)
x <- r
} yield (r, x)
}
// rangeElements(3) returns an empty sequence
// rangeElements(4) returns the sequence (Range(0,1,2,3), 0), (Range(0,1,2,3), 1) etc.
这给了我两个类型不匹配的编译器错误。 r <- createRange(n) 行需要 Seq[Int],但找到了 scala.util.Try[Nothing]。 x <- r 行需要 scala.util.Try[?] 但找到 scala.collection.immutable.IndexedSeq[Int]。
大概是 Try 的某种类型擦除让我很困惑,但我不知道它是什么。我在 for comprehension 中尝试了各种 toOption 和 toSeq 限定词无济于事。
如果我只需要生成范围元素,我可以按照下面前两个答案的建议,自己显式处理createRange 的Success 和Failure 条件。但是,我需要访问范围及其各个元素。
我意识到这是一个听起来很奇怪的例子。我要解决的真正问题是复杂的递归搜索,但我不想添加它的所有细节,因为这只会混淆这里的问题。
如何编写rangeElements 以产生所需的序列?
【问题讨论】:
标签: scala exception for-comprehension