探索を続けるwith文

2488 ワード

前のブログ「きれいなwith、魚と熊の掌を兼ねることができる」では、withの優雅さを示したが、with|>を比較すると、言葉が尽きず、説明が不十分だった.
そのブログで、私はこう言いました.
結局with/1はtry/catchではなく、実行中に投げ出されたエラーをキャプチャしてelseに移行してエラー処理を行うことはできません.モードマッチングにエラーが発生した場合にのみelseに移行します.
エラーを優雅に処理し、優雅なwith/1で論理を直列に接続するにはget_を再構築する必要があります.user,get_response,send_responseなどの関数.プログラムロジックが正しい場合、tupleオブジェクト{:ok,result}を返します.エラーが発生した場合は{:error,error}を返します.
このような再構築が行われれば、|>も丈夫さと優雅さを結びつけることができることを意味するのだろうか.Elixirでは、関数の定義にパターンマッチングが用いられるため、|>の動作に関与する関数を定義する際に、パターンマッチングによって様々な状況を考慮することができ、{:error, error}の場合の処理を含んで、その関数を流れる際にエラーによってデータストリームがクラッシュしないようにすることができる.
Joseph KainはブログLearning Elixir's withでectoクエリーを実行する例を示した.
defp results(conn, search_params) do
    conn.assigns.current_user
    |> Role.scope(can_view: Service)
    |> within(search_params)
    |> all
    |> preload(:user)
end

defp within(query, %{"distance" => ""}), do: {:ok, query}
defp within(query, %{"distance" => x, "location" => l} do
    {dist, _} = Float.parse(x)
  Service.within(query, dist, :miles, l)
end 
defp within(query, _), do: {:ok, query}

defp all({:error, _} = result), do: result
defp all({:ok, query}), do: {:ok, Repo.all(query)}

defp preload({:error, _} = result), do: result
defp preload({:ok, enum}, field) do
    {:ok, Repo.preload(enum, field)}
end 

業務にかかわらず、allおよびpreload関数において{:error, _}分岐の処理が増加したことを明確に見ることができ、これにより、データフローのパイプラインがエラーによって終了することを回避することができる.withを使用すると、|>よりも構造が明瞭で直感的ではないが、allおよびpreloadにおけるエラーブランチの処理を回避することができる.with文は同様にパターンマッチングを使用するため、参加する方法がパターンマッチングの条件を満たすことができない限り、doは実行されず、エラーによる終了を回避する.
defp results(conn, search_params) do
    with user  ""}), do: {:ok, query}
defp within(query, %{"distance" => x, "location" => l} do
    {dist, _} = Float.parse(x)
  Service.within(query, dist, :miles, l)
end 
defp within(query, _), do: {:ok, query}

defp all(query), do: Repo.all(query)
defp preload(enum, field) do: {:ok, Repo.preload(enum, field)}
all/1およびpreload/2は、Repo.all/1およびRepo.preload/2の単純パッケージにすぎないので、コードをさらに簡略化することができる.
defp results(conn, search_params) do
    with user 

余分なコードは効果的に消去され、機能と丈夫性は低下しなかった.これはwithinの奇妙なところです.