Either Type In Scala

Hôm nay mình sẽ giới thiệu về một kiểu đặt biệt trong Scala, đó là Either.
Theo định nghĩa trên trang: http://www.scala-lang.org/api/rc2/scala/Either.html

Represents a value of one of two possible type (a disjoint union). Instances of Either are either an instance of Left or Right.

Chúng ta sẽ cùng nhau tìm hiểu qua một vài ví dụ. Trước tiên chúng ta sẽ viết một hàm convert một string ra Integer:

def toInt(str: String): Either[String, Int] = {
    try {
      Right(str.toInt)
    } catch {
      case e: Exception => Left("Error: " + e.getMessage)
    }
  }

toInt("convert") match {
      case Left(msg) => println(msg)
      case Right(x) => println("Passed the Int: " + x)
    } //> Error: For input string: "convert"

Không giống như Try hay Option, để sử dụng Either chúng ta cần làm rõ chúng ta muốn điều kiện đúng là Right hay Left. Chúng ta có thể lấy ra giá trị của LeftProjection or RightProjection bằng cách gọi: .right or .left.
Khi đã xác định được projection là left or right ta có thể sử dụng map (Trong ví dụ trên là right):

toInt("1").right.map(x => println("Passed the Int: " + x)) //> Passed the Int: 1

Chúng ta cũng có thể sử dụng Flatmap trong ví dụ, chúng ta sử dụng hàm toInt ở trên để tính tổng của 2 số truyền vào dưới dạng string:

val sum = toInt("2").right.flatMap(x =>
      toInt("4").right.map(y =>
        x + y
      )
    )

Nhân tiện đây mình cũng giới thiếu với các bạn cách dùng For Comprehensions. Chúng ta sẽ viết lại logic tính tổng của 2 số trên theo cách:

def sum(str1: String, str2: String): Either[String, Int] =
    for {
      x <- toInt(str1).right
      y <- toInt(str2).right
    } yield x + y

OK, qua các ví dụ trên chúng ta đã hiểu được cách sử dụng Either trong Scala. Như đã trình bày trong bài viết: Error Handling in Scala, với Either chúng ta có thêm một phương thức nữa để Error Handling:

case class FailResult(reason:String)

def parse(input:String) : Either[FailResult, String] = {
  val r = new StringTokenizer(input)
  if (r.countTokens() == 1) {
    Right(r.nextToken())
  } else {
    Left(FailResult("Could not parse string: " + input))
  }
}

Hẹn gặp lại trong các bài chia sẻ tiếp theo.

Refer: http://www.scala-lang.org/api/rc2/scala/Either.html
https://tersesystems.com/2012/12/27/error-handling-in-scala/

Add a Comment

Scroll Up