(この記事は、「fukuoka.ex x ザキ研 Advent Calendar 2017」の15日目です)
昨日は@piacere_exさんの「関数型でデータサイエンス#3:インプットしたデータを集約する①」でした.
追記 2019/02/24
現在,リストの操作は再帰ではなく,Enum.map/reduceを推奨しています.
また,下記の実装内容については,「[Elixir]再帰/逐次アクセスをEnum.Map/Reduceに書き換え(本編)](https://qiita.com/hisaway/items/f69b48bd7611ed9b5be2)」の方が参考になると思います.
map/reduceのメリット
- 可読性がよくなる
- パイプライン演算子が使いやすい
- 副次的な効果としてパイプライン演算子を使うために関数の設計規則が自然と統一される
- 並列プログラミング処理系「Hastega」の恩恵を受けられる(予定)
#はじめに
前回の記事「Elixirで再帰呼び出しを使ってリストの加算関数をつくる」では,2つの1次元リストを加算する関数について説明しました。
- 関数にはガード句を使って呼び出し条件が設定できる
- 関数の引数にリストのパターンマッチングを適用することで、呼び出し条件を設定できる
この記事では,1次元リストの拡張、2次元リストの加算関数について説明します.
前回の記事に引き続き、ガード句とパターンマッチングを使用します.
忘れた方は、前回の記事に再度目を通しておきましょう。
2次元リスト
挙動の確認
関数を作る前に2次元リストの挙動を確認してみましょう。
iex(1)> list = [ [1,2], [3,4] ]
[[1, 2], [3, 4]]
iex(2)> hd list
[1, 2]
iex(3)> teal = tl list
[[3, 4]]
iex(4)> tl teal
[]
関数の呼び出し条件
2次元リストの加算関数は「ガード句」と「パターンマッチング」のどちらも使います。
引数に使用したリストのパターンマッチングはそのままです。上記で確認した挙動から、リストのhead
がリストであれば、2次元リストだと判断することができます。
defmodule Test do
def add([a | tla], [b | tlb]) when is_list(a) do
inspect [add(a,b)|add(tla, tlb)], charlists: :as_lists
end
end
確認
実際に,動かしてみましょう.
iex(1)> list2a = [ [1, 2], [3, 4] ]
[[1, 2], [3, 4]]
iex(2)> list2b = [ [5, 5], [5, 5] ]
[[5, 5], [5, 5]]
iex(3)> Test.add(list2a, list2b)
"[[6, 7] | \"[[8, 9]]\"]"
inspect~ , charlist: :as_lists
はリスト内の数値を正しく表示するために使用しています.
inspect
なしだと,iex
の仕様か,表示がおかしくなることがあります.
iex(1)> Test.add([ [1, 2], [3, 4]], [ [5, 5], [5, 5] ])
[[6, 7], '\b\t']
iex(2)> Test.add([ [1, 2], [3, 4]], [ [5, 5], [1, 2] ])
[[6, 7], [4, 6]]
まとめ
標準のリスト表示が納得いきませんが,2次元リストの加算関数を実装しました.
要点をまとましょう.
- ガード句とパターンマッチングは併用できる
- 2次元リストだと表示が上手くいかないことがあるので注意
明日は @Takeshi-Kogu さんの「モジュールをファイルに書き込んでみる(前半)」 です。お楽しみに!