使用guard子句提前退出函数的Scala方法是什么?
我想知道是否有一种惯用的方法,可以在满足条件时使用guard子句提前离开一个方法 在其他语言中,我会这样做:使用guard子句提前退出函数的Scala方法是什么?,scala,Scala,我想知道是否有一种惯用的方法,可以在满足条件时使用guard子句提前离开一个方法 在其他语言中,我会这样做: def myFunction(): Either[String, String] = { if (someErrorCondition) return Left("error msg") // Rest of the code } 然而,这对我来说似乎是错误的,因为使用return似乎不是惯用的方法。我曾考虑过: def myFunction(): Either[St
def myFunction(): Either[String, String] = {
if (someErrorCondition)
return Left("error msg")
// Rest of the code
}
然而,这对我来说似乎是错误的,因为使用return
似乎不是惯用的方法。我曾考虑过:
def myFunction(): Either[String, String] = {
if (someErrorCondition)
Left("error msg")
else
// Rest of the code
}
但这很难看,意味着需要多个守卫的地方有很多if-else
关于如何正确地做到这一点,有什么建议吗 附和其他人,依我看,条件表达不是惯用表达的观点是错误的,因此以下几点对我来说似乎没问题
if (errorCondition1) Left("error msg 1")
else if (errorCondition2) Left("error msg 2")
else Right(42)
早期返回或短路的思想在理解中是固有的,因此这里有一种非常规的方法,通过扩展方法将布尔值
转换为Eithers
,其中真
转换为左
implicit class GuardToLeft(p: Boolean) {
def toGuard[L](left: => L): Either[L, Unit] =
if (p) Left(left) else Right(())
}
所以现在我们可以像这样模拟传统的早退后卫
for {
_ <- errorCondition1.toGuard("error msg 1")
_ <- errorCondition2.toGuard("error msg 2")
} yield {
41 + 1
}
用于{
_FP方法是使用具有某种形式的内置错误处理功能的类型,例如或
假设String
是您的错误格式。然后您可以使用flatMaps
-for提前返回(“断路”)-for或者Left
是错误格式,Right
用于线程化正在进行的计算:
import scala.util._
def sqrtFromString(argument: String): Either[String, Double] = {
val start: Either[String, String] = Right(argument) // just for upcasting Right to Either
start
// if start is Right, then value inside it will be passed as string variable
// Right will continue computation
// Left will circuit break them
.flatMap { string =>
Try(string.toInt) match {
case Success(int) => Right(int)
case Failure(_) => Left("Not integer")
}
}
// if so far it is still Right, the value inside will be passed as int variable
.flatMap { int =>
if (int > 0) Right(int)
else Left("Negative int")
}
// if Right, it still will be Right - no ability to circuit break using map
.map { int =>
Math.sqrt(int)
}
}
由于map
和flatMap
由for
理解处理,因此您可以将其重写为:
import scala.util._
def sqrtFromString(argument: String): Either[String, Double] =
for {
string <- (Right(argument): Either[String, String])
int <- Try(string.toInt) match {
case Success(int) => Right(int)
case Failure(_) => Left("Not integer")
}
positive <- {
if (int > 0) Right(int)
else Left("Negative int")
}
} yield Math.sqrt(positive)
导入scala.util_
def sqrtFromString(参数:String):要么[String,Double]=
为了{
左字符串(“非整数”)
}
正0)右(int)
左偏左(“负整数”)
}
}产量数学sqrt(正)
可进一步缩短为:
def sqrtFromString(argument: String): Either[String, Double] =
for {
string <- Right(argument)
int <- Try(string.toInt).toEither.left.map(_ => "Not integer")
_ <- (if (int > 0) Right(()) else Left("Negative int"))
} yield Math.sqrt(int)
def sqrtFromString(参数:String):要么[String,Double]=
为了{
没有else的字符串if
通常会导致错误的类型(因为它返回的是单元实际上
)。许多if else
有什么问题吗?但是,由于您使用的是其中之一,您可以利用它是flatMap
左侧短路。还有一个helper方法other.cond(布尔,右,左)
并将它们全部链接到大屏幕上,以便于理解。我认为,if-else
绝对没有错。我同意引导ifs是丑陋和令人分心的。对于单个if,将其放在一行,def=if(cond)fail()else{
与“真实身体”的其余部分一起正常识别。否则在函数中坚持验证,def:other[a,B]=validated.map(body)
(没有人说:问题是Scala中有多少种方法可以执行X?)谢谢大家的评论和回答。我想这只是我对多个if-else
丑陋的审美感受,因为我必须在整个方法中添加一个缩进级别,仅仅是因为第一个条件。早期返回是治疗if
语句的多个缩进的方法。这很不传统。@RoberHarvey这正是我在问题中试图表达的观点之一。但是如何在Scala中实现早期返回而不使用return
语句?早期返回根据定义使用return
。Scala.util
而不使用复数。