Elixir

関数を引数で渡して、渡した先で関数を走らせる

処理の大半は、同一の処理を共有したいけど、一部だけ挙動を変えたい、といったとき、関数を引数で渡すテクニックが、役に立つ

下記の例は、HTTP GETでJSON API結果を拾った後に、list_mapを加工する関数を引数渡しして、加工後を返す例

defmodule Json do
    def get( domain, path, header \\ [], map_function \\ &nop/1 ) do
        domain <> path
        |> HTTPoison.get!( header )
        |> parse( map_function )
    end

    defp parse( response, map_function ) do
        response
        |> get_body
        |> Poison.decode!
        |> map_function.()
    end

    defp get_body( %{ status_code: 200, body: body } ), do: body
    defp nop( map_list ), do: map_list
end

呼び出し側は、こんな感じで、「&」とアリティ付きで指定する(未指定時は、デフォルト引数で無加工の関数が呼ばれる)

defmodule GithubWrapper do
    def run(), do: Json.get( "https://api.github.com", "/rate_limit", &pick_rate/1 )
    defp pick_rate( %{ "rate" => rate } ), do: rate
end

無名関数って、Enum.map()等の高階関数の中で使うケースは多いけど、function.()の形式で使うことは少ないんだが、上記みたいなライブラリ/FW側を作るときには、案外、重宝する

あと、こうしたケースをスマートに書くには、「渡す関数の引数を1個に限定する」という、モナドっぽい考え方がコツ