[英]Scala Yeild returning Try[Either[]] rather then Either
我正在尝试对 scala 基本操作进行一些动手操作,并在以下示例代码中陷入困境
def insuranceRateQuote(a: Int, tickets:Int) : Either[Exception, Double] = {
// ... something
Right(Double)
}
def parseInsuranceQuoteFromWebForm(age: String, numOfTickets: String) : Either[Exception, Double]= {
try{
val a = Try(age.toInt)
val tickets = Try(numOfTickets.toInt)
for{
aa <- a
t <- tickets
} yield insuranceRateQuote(aa,t) // ERROR HERE
} catch {
case _ => Left(new Exception)}
}
我得到的错误是它说found Try[Either[Exception,Double]]
我不明白为什么它是 Try of Either 下的包装器
PS - 这一定不是在 scala 中做的完美方式,所以请随时发布您的示例代码:)
要理解的关键是,理解可能会改变包装器内部的内容,但不会改变包装器本身。 原因是因为对map
/ flatMap
的理解脱糖调用链的第一步中确定的包装器。 例如考虑以下代码片段
val result: Try[Int] = Try(41).map(v => v + 1)
// result: scala.util.Try[Int] = Success(42)
请注意我们如何将Try
包装器中的值从41
转换为42
,但包装器保持不变。 或者,我们可以使用 for-comprehension 来表达同样的事情
val result: Try[Int] = for { v <- Try(41) } yield v + 1
// result: scala.util.Try[Int] = Success(42)
注意效果是如何完全相同的。 现在考虑以下链接多个步骤的理解
val result: Try[Int] =
for {
a <- Try(41) // first step determines the wrapper for all the other steps
b <- Try(1)
} yield a + b
// result: scala.util.Try[Int] = Success(42)
这扩展到
val result: Try[Int] =
Try(41).flatMap { (a: Int) =>
Try(1).map { (b: Int) => a + b }
}
// result: scala.util.Try[Int] = Success(42)
我们再次看到结果是相同的,即在包装器内部转换的值但包装器保持未转换。
最后考虑
val result: Try[Either[Exception, Int]] =
for {
a <- Try(41) // first step still determines the top-level wrapper
b <- Try(1)
} yield Right(a + b) // here we wrap inside `Either`
// result: scala.util.Try[Either[Exception,Int]] = Success(Right(42))
原理保持不变 - 我们确实将a + b
包装在Either
中,但这不会影响仍然是Try
的顶级外部包装器。
Mario Galic 的回答已经解释了您的代码的问题,但我会以不同的方式解决它。
两点:
Either[Exception, A]
(或者更确切地说, Either[Throwable, A]
)有点等价于Try[A]
, Left
扮演Failure
角色, Right
扮演Success
角色。
外部的try
/ catch
没有用,因为异常应该通过在Try
中工作来捕获。
所以你可能想要类似的东西
def insuranceRateQuote(a: Int, tickets:Int) : Try[Double] = {
// ... something
Success(someDouble)
}
def parseInsuranceQuoteFromWebForm(age: String, numOfTickets: String): Try[Double] = {
val a = Try(age.toInt)
val tickets = Try(numOfTickets.toInt)
for{
aa <- a
t <- tickets
q <- insuranceRateQuote(aa,t)
} yield q
}
有点不幸的是,如果您弄清楚理解的作用,这会产生无用的map(q => q)
,因此您可以更直接地将其编写为
a.flatMap(aa => tickets.flatMap(t => insuranceRateQuote(aa,t)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.