JavaScriptにおける実用的関数プログラミング


こんにちは.エラー処理についての全ポストに到着しました.

コミッククレジットhttps://xkcd.com/2303/
今日はJavaScript関数型プログラミングのエラーについてお話します.エラーは期待を設定することです、そして、期待が現実を逃すとき、バグは起こります.適切なエラー処理(スローとキャッチの両方)はバグを少なくコードを書くキーです.この記事では、JavaScriptのエラー処理のための現在および歴史的な方法を調べ、現在のJavaScript構文を使用してエラーを処理するための良い一般的な方法を解決しようとします.私はまた、最後に(私のライブラリから)機能をプラグインします.
さらにADOがなければ、JavaScript関数型プログラミングでエラーが起こっていることを見ましょう

  • Elegant error handling with the JavaScript Either Monad .
  • Functional Error Handling
  • Functional Programming in TypeScript
  • これらの自分自身をクリックして自由に感じるが、私はあなたのトラブルを保存します-すべての3つの記事の行に沿って何かを言うエラーをスローする代わりに、いずれかのモナドを使用します.
    通常、私はイディオムを置き換えることは良いことは何かについて行くための良い方法ではないと思う.Monadsを調査することによって、我々自身の判断をしましょう.What is a monad ?

    a monad is an abstraction that allows structuring programs generically while automating away boilerplate code needed by the program logic.


    また、モナドhave a spec . モナドは
  • 型コンストラクタ-プロトタイプを持つもの
  • function MyMonad(x) {...}
  • 型コンバーター-値をmonadに得る方法
  • MyMonad.of = x => new MyMonad(x)
  • コンビナータ-モナドの複数のインスタンスを結合する方法
  • myMonad.chain(anotherMyMonad) -> combinedMyMonadのいずれかです.以下はmonad実装の最小値です.
    function Left(x) {
      this.value = x
    }
    
    function Right(x) {
      this.value = x
    }
    
    function Either(leftHandler, rightHandler, x) {
      return x.constructor === Left ? leftHandler(x.value) : rightHandler(x.value)
    }
    
    ここではどのようにモナドを使用します.
    // parseJSON(s string) -> Either<Left<Error>, Right<Object>>
    const parseJSON = s => {
      try {
        return new Right(JSON.parse(s))
      } catch (err) {
        return new Left(err)
      }
    }
    
    Either(
      err => console.error(err), // Left
      parsed => console.log(parsed), // Right
      parseJSON('{"a":1,"b":2,"c":3}'),
    ) // { a: 1, b: 2, c: 3 }
    
    どちらかのモナドとの方法は確かに純粋に見えますが、それは本当にAよりも優れているtry catch ブロック?
    try {
      const parsed = JSON.parse('{"a":1,"b":2,"c":3}')
      console.log(parsed)
    } catch (err) {
      console.error(err)
    }
    
    上に直接バニラtry catch 前の例でMonadのどちらかを行うブロック.上のスニペットは、parseJSON 左と右のmonadsのための機能は、一般的により簡潔です.私は、どちらかのmonadの利益がすでにあるとき、見ませんtry catch ブロックとthrow . 私の意見は、モナドがどんな重大な使用のためにでも十分な重さ対通常のJavascript構文を引っ張らないということです.しかし、私はモナドが機能的なスタイルを促進するようにします.
    非同期コールバックハンドラーでは、monadに似たような短絡パターンがあります.
    function asyncFunc(userID, cb) {
      getUserByID(userID, (err, user) => {
        if (err) {
          cb(err) // new Left(err)
        } else {
          cb(null, user) // new Right(user)
        }
      })
    }
    
    asyncFunc('1', (err, user) => {
      if (err) console.error(err) // Left
      else console.log(user) // Right
    })
    
    左と右はコールバックの構文に焼きます.errならば、左のものをしてください、さもなければ、正しいことをしてください.これはコールバックのためによく働きました、しかし、約束が出たとき、多くの人々は動きました.
    const promiseFunc = userID => new Promise((resolve, reject) => {
      getUserByID(userID, (err, user) => {
        if (err) {
          reject(err) // new Left(err)
        } else {
          resolve(user) // new Right(user)
        }
      })
    })
    
    promiseFunc('1')
      .then(user => console.log(user)) // Right
      .catch(err => console.error(err)) // Left
    
    約束は、どちらかのモナドに気まぐれに似ています.まるで約束が残されたかのようなもので、どちらかが一つになった.約束についてのことは、彼らは左と右のパスを表現する唯一の目的のために作成されていないということです.代わりに、非同期操作をモデル化するために作成されました.
    async/waitを使うと、エラー処理の最新版があります
    try {
      const user = await promiseFunc('1')
      console.log(user) // Right
    } catch (err) {
      console.error(err) // Left
    }
    
    最新でasync/await 構文try catch ブロックはcurrent prescribed way エラーを処理する.あなたが幸せであるならばtry catch ブロックは、ここで読んで停止することができますように、購読し、あなたの陽気な方法でオフスマッシュ.しかし、行く前に、ライブラリ関数を使ってエラーを処理するクリーンな方法があります.私の関数型プログラミングライブラリ、Rubisoからの雹、それはtrycatchです!
    /*
     * @synopsis
     * <T any>tryCatch(
     *   tryer (x T)=>any,
     *   catcher (err Error, x T)=>any,
     * )(x T) -> Promise|any
     */
    
    tryCatch(
      async userID => {
        const user = await promiseFunc(userID)
        console.log(user) // Right
      },
      err => console.error(err), // Left
    )('1')
    
    tryCatch(
      jsonString => {
        const parsed = JSON.parse(jsonString)
        console.log(parsed) // { a: 1, b: 2, c: 3 }
      },
      err => console.error(err),
    )('{"a":1,"b":2,"c":3}')
    
    RubisoのtryCatch すべてのエラー、同期または非同期をキャッチするため、クールです.私は個人的には、すべての種類のエラーを処理するために1つのインターフェイスを必要とするだけで好きです.そのことは議論できたtry catch with await 同じことをするでしょうが、その時点で、あなたは既に約束の土地にいて、同期している土地に戻ることができません.RubisoのtryCatch は同期的にスローされたエラーに対して完全に同期して動作します.Sync vs Asyncは、Rubyの正しさを最初に取るに足らないように見えるかもしれませんが、実際にはこれが良いことであり、それが保証であり、心配する必要はありません.あなたが至福の同様のレベルで機能的なプログラミングを始めたいならば、チェックアウトしてくださいrubico 今日.
    最後に、私はモナドが大好きです.私は、彼らが超クールであると思います、しかし、彼らは彼らが実際にあなたがバニラJavascriptでそうすることができたより何かをする場所でだけ使われるべきです.monadsを使用するためのモナドを使用して、まあ、mehです.JavaScriptは、JavaScriptであるマルチパラダイム言語の恩恵を受けるモナドである.あなたがそのようなモナドを知っているならば、私はコメントでそれについて聞くのが好きです.
    読書ありがとう!これは、JavaScriptで私のシリーズ実用的な機能プログラミングを終了します.あなたはRubisoのシリーズの残りの部分を見つけることができますawesome resources . あなたが私にあなたがブログに好きである何かを持つならば、私はコメントでそれを聞くのも好きです.TBDで次回お会いしましょう!
    カバー写真クレジット:
    https://resilientblog.co/inspirational/quotes-about-mountains/
    ソース
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
    https://en.wikipedia.org/wiki/Monad_(functional_programming)
    https://en.wikipedia.org/wiki/Kleisli_category