23

Option (単純な値の場合) や、エラーの処理に [List[Error], T] を使用する scala コードを何度も見てきました。

これは、このようなコードに場所を与えます

def createApplicationToken(accessToken: AccessToken): Either[List[Error], ApplicationToken] = {

// go to social info provider and fetch information
retrieveProviderInfo(accessToken).fold(
  errors  => Left(errors),
  info    => {
    // try to find user using the info from the provider
    // if it's not there, create user
    User.findOrCreateFromProviderInfo(info).fold(
      errors  => Left(errors),
      user    => {
        // try to create a fresh token and save it to the user
        user.refreshApplicationToken.fold(
          errors  => Left(errors),
          user    => Right(user.token)
        )
      }
    )
  }
)

これはあまり良くないコードの入れ子を生成し、すべてのステップで失敗に対処することを強制し、すべての関数がいずれかを返すように強制します[...]

だから私は知りたいです

  • scala (または一般的な関数型プログラミング) では、例外の使用は推奨されません。

  • それらを使用することには欠点があります(不変性またはコードの同時実行性に関して)

  • 例外が原則または関数型プログラミングと何らかの形で矛盾している

  • 与えられた例をコーディングするより良い方法を考えることができます

--

returnステートメントを使用してエラーが見つかったらすぐに関数を終了することでネストを回避できますが、scalaではreturnの使用も推奨されません...

4

3 に答える 3

24

次のバージョンでは、 の正しい射影がEitherモナドであるという事実を使用しており、コードとまったく同じです。

def createApplicationToken(accessToken: AccessToken) = for {
   info <- retrieveProviderInfo(accessToken).right
   user <- User.findOrCreateFromProviderInfo(info).right
   refr <- user.refreshApplicationToken.right
} yield refr.token

そして、 の利点を誇示するために、はるかに優れた仕事をしEitherます。

より一般的には、規則は Java と同じです。例外的な状況には例外を使用します。このスタイルで作業している場合、例外の定義を少し変更することに気付くかもしれません。たとえば、無効なユーザー入力は実際には例外ではなく、タイムアウトになったネットワーク リクエストは実際には例外ではありません。

EitherScala 2.12 から右バイアス

を省略できる.rightようになったため、次のコードは Scala 2.12 以降と同等です。

def createApplicationToken(accessToken: AccessToken) = for {
   info <- retrieveProviderInfo(accessToken)
   user <- User.findOrCreateFromProviderInfo(info)
   refr <- user.refreshApplicationToken
} yield refr.token
于 2012-10-22T13:40:33.013 に答える
6

om-nom-nom が言ったように、私は同様の質問をしました: Scala で例外をスローする、「公式ルール」とは

しかし、パターン マッチングなどのために多くの定型コードと多くのインデント レベルを使用してコーディングしていたため、興味があるかもしれないと尋ねたのはそれだけではありません...


于 2012-10-22T14:05:38.240 に答える
2

答えは、理想的なものと実際的なものの間で異なります。理想的には、例外を使用しないでください。実際には、それらなしでは生きられません。

Scala はワンライナーを支持しているようで、それに沿って v2.10 には新しいモナドTryがあります:

import scala.util.Try

def percentCompleted( total:Int, done:Int ): Int = Try (done * 100 / total) getOrElse 100

percentCompleted( 0, 10 )    // Catches divide-by-zero and returns 100% instead
于 2012-10-22T15:07:09.653 に答える