fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます
前回のコラムで、ifが、引数を2つ取る関数であることを解明しました
このことを利用して、パイプの中で、ifを使う方法について解説します
パイプでifの第1引数を渡す
ifは、以下のように、第1引数に条件、第2引数に「do:」と「else:」のキーワードリストを取ります
iex> if( "abc" == "abc", do: "abc is abc", else: "abc is not abc" )
"abc is abc"
iex> if( "abc" == "xyz", do: "abc is abc", else: "abc is not abc" )
"abc is not abc"
これをパイプで書き直すと、こうなります
iex> ( "abc" == "abc" ) |> if( do: "abc is abc", else: "abc is not abc" )
"abc is abc"
なお、パイプで渡す部分をカッコで囲まないと、うまく動きませんので、注意してください
iex> "abc" == "abc" |> if( do: "abc is abc", else: "abc is not abc" )
false
iex> "abc" == "xyz" |> if( do: "abc is abc", else: "abc is not abc" )
false
パイプで繋いだ処理の中でifを使う
以下のような、0~10までの数字列のうち、3で割り切れるものだけ、trueを返す処理があったとします
iex> 0..10 |> Enum.map( &( rem( &1, 3 ) == 0 ) )
[true, false, false, true, false, false, true, false, false, true, false]
この処理の中で、ifを挟むと、以下のような、trueになった数字だけをピックアップできます
iex> 0..10 |> Enum.map( &( ( rem( &1, 3 ) == 0 ) |> if( do: &1 ) ) )
[0, nil, nil, 3, nil, nil, 6, nil, nil, 9, nil]
nilをEnum.filterで除去すると、こんな感じになります
iex> 0..10 |> Enum.map( &( ( rem( &1, 3 ) == 0 ) |> if( do: &1 ) ) ) |> Enum.filter( &( &1 != nil ) )
[0, 3, 6, 9]
ifをパイプ中で使う方法が、お分かりになったでしょうか?
ifをパイプで書かなくてもいいし、ifを使わなくてもいい
なお、このサンプルは、以下のように、普通のif文で書き直すこともできます
iex> 0..10 |> Enum.map( &( if rem( &1, 3 ) == 0, do: &1 ) ) |> Enum.filter( &( &1 != nil ) )
[0, 3, 6, 9]
1行ifの強力さを実感できますね
更に単純化すると、以下の通りです
iex> 0..10 |> Enum.filter( &( rem( &1, 3 ) == 0 ) )
[0, 3, 6, 9]
ifが無くなってしまいました
全てのケースが、ここまで単純化できるかは、何とも言えませんが、Enumをマスターしていくと、データの塊を処理する際に、if文での判定が不要になっていくニュアンスを、ここから何となく受け取っていただけたら幸いです