使用 Either 表示错误
Left 与 Right
使用 Either 表示错误 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
为什么使用 Either?
Either 表示一个值可能是两种情况之一。它是对可能失败、并且需要提供失败信息的计算进行建模的惯用方式。
Left通常存放错误。Right通常存放成功值。
与只表示某个值缺失的 Option 不同,Either 会告诉您出了什么问题。
Either 类型
Either[A, B] 是一个密封特征,包含两个子类型:Left[A] 和 Right[B]。
记忆方法是:Right 就是正确的,Left 表示错误。按照这一约定,map 和 flatMap 会自动作用于成功侧。
val ok: Either[String, Int] = Right(42)
val err: Either[String, Int] = Left("boom")
println(ok)
println(err)从函数返回 Either
可能失败的函数会返回 Either,而不是抛出异常。这样,调用方就可以显式处理两种结果。
object Main {
def parseAge(s: String): Either[String, Int] =
s.toIntOption match {
case Some(n) if n >= 0 => Right(n)
case Some(_) => Left("age cannot be negative")
case None => Left("not a number")
}
def main(args: Array[String]): Unit = {
println(parseAge("30"))
println(parseAge("-5"))
println(parseAge("x"))
}
}对 Either 进行模式匹配
使用 Either 最直接的方式是模式匹配,分别处理 Left 和 Right。
@main def run(): Unit = {
val result: Either[String, Int] = Right(10)
val msg = result match {
case Right(value) => s"Got value: $value"
case Left(error) => s"Failed: $error"
}
println(msg)
}fold:合并两侧
fold 接收两个函数:一个处理 Left,另一个处理 Right,并生成一个具有共同类型的结果。
当您希望得到一个值时,它是模式匹配的简洁替代方案。
@main def run(): Unit = {
val r: Either[String, Int] = Right(7)
val label = r.fold(
err => s"error: $err",
num => s"double is ${num * 2}"
)
println(label)
}map 作用于 Right
map 会转换 Right 中的值,而保持 Left 不变。这就是 Scala Either 的右偏行为(从 2.12 版本开始)。
@main def run(): Unit = {
val ok: Either[String, Int] = Right(5)
val no: Either[String, Int] = Left("missing")
println(ok.map(_ + 1))
println(no.map(_ + 1))
}getOrElse 与默认值
getOrElse 会提取 Right 中的值;如果 Either 是 Left,则返回备用值。
@main def run(): Unit = {
val ok: Either[String, Int] = Right(99)
val no: Either[String, Int] = Left("oops")
println(ok.getOrElse(0))
println(no.getOrElse(0))
}swap:交换两侧
swap 会交换 Left 和 Right。当您希望使用右偏方法处理错误侧时,这很有用。
@main def run(): Unit = {
val err: Either[String, Int] = Left("bad input")
val swapped = err.swap.map(_.toUpperCase)
println(swapped)
}isLeft 与 isRight
通过快速的布尔检查,您无需进行完整的模式匹配就可以进行分支处理。
isRight在成功时返回 true。isLeft在出错时返回 true。
@main def run(): Unit = {
val r: Either[String, Int] = Right(1)
println(r.isRight)
println(r.isLeft)
}toOption:丢弃错误
当您不再关心失败的原因时,toOption 会将 Either 转换为 Option:Right(x) 变为 Some(x),Left(_) 变为 None。
@main def run(): Unit = {
val ok: Either[String, Int] = Right(3)
val no: Either[String, Int] = Left("err")
println(ok.toOption)
println(no.toOption)
}验证示例
综合运用:验证用户名,并在失败时返回带有类型的错误。
object Main {
def validate(name: String): Either[String, String] =
if (name.isEmpty) Left("empty name")
else if (name.length > 10) Left("name too long")
else Right(name)
def main(args: Array[String]): Unit = {
println(validate("alice"))
println(validate(""))
println(validate("verylongusername"))
}
}快速检查
检验您对 Either 约定的理解。
回顾
您已经学习了如何使用 Either 对错误建模:
Right= 成功,Left= 错误(右偏)。- 使用模式匹配或
fold处理结果。 - 使用
map转换成功值;使用getOrElse提供默认值。 - 使用
swap交换两侧;使用toOption进行转换。
接下来,您将使用 Try 处理异常。
常见问题解答
「使用 Either 表示错误」课时是免费的吗?
是的 — 「使用 Either 表示错误」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
「使用 Either 表示错误」这节课中我会学到什么?
Left 与 Right 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用 Either 表示错误」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?
能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 Either 表示错误
- Try、Success、Failure
- 组合 Either
- 类型之间的转换