使用guard子句提前退出函数的Scala方法是什么?

使用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

我想知道是否有一种惯用的方法,可以在满足条件时使用guard子句提前离开一个方法

在其他语言中,我会这样做:

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
而不使用复数。