アナグラムのコードをタスクとエージェントを使って書き直す
Kernel.to_char_list/1
が非推奨だったので Kernel.to_charlist/1
に変更した
String.strip/1
が非推奨だったので String.trim/1
に変更した
goh@goh% iex tasks/anagrams.exs
Erlang/OTP 21 [erts-10.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
> Dictionary.start_link
{:ok, #PID<0.108.0>}
> Enum.map(1..4, &"tasks/words/list#{&1}") |> WordlistLoader.load_from_files
[:ok, :ok, :ok, :ok]
> Dictionary.anagrams_of "organ"
["ronga", "rogan", "orang", "nagor", "groan", "grano", "goran", "argon",
"angor"]
Dictionary.start_link/0
空のマップを初期値にしてプロセスを開始する
Dictionary.add_words(words)
- words: 単語のリスト
単語を登録する
内部では
do_add_words/2
を呼び出している
Dictionary.anagrams_of(word)
- word: アナグラムの対象
指定した単語のアナグラムを取得する
内部では
Map.get/2
を呼び出しているMap.get/2
に第2引数はsignature_of/1
の戻り値
Dictionary.do_add_words(map, words)
- map: 辞書
- words: 単語のリスト 単語のリストの要素を使って以下の関数を呼び出す
add_one_word(word, map)
Dictionary.add_one_word(word, map)
- word: 単語リストの要素
- map: 辞書 辞書(マップ)に以下の要素を追加する
- key:
signature_of(word)
の戻り値 - value:
signature_of/1
の戻り値が同じ単語のリスト
Dictionary.signature_of(word)
word
に使われている文字を文字のリストに変換、ソート、連結して文字列化する
WordlistLoader.load_from_files(file_names)
- file_names: ファイル名のリスト
各ファイルから単語を読み込む
内部では
WordlistLoader.load_task/1
を呼び出しているload_task/1
の引数はfile_names
の各ファイル名Task.async/1
でload_task/1
を呼び出すことで、複数プロセスで処理させ、Task.await/1
で回収している
`WordlistLoader.load_task(file_name)
- file_name: ファイルの名前
指定されたファイルから単語を読み込み、辞書に登録する
1行ごとに読み込み、トリムし、
Dictionari.add_words/1
に渡している
エージェントにグローバルでアクセスできる名前を付けるだけで、分散実行可能になる
ノード one
goh@goh% iex --sname one tasks/anagrams_dist.exs
Erlang/OTP 21 [erts-10.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(one@goh)1> Node.list
[:two@goh]
iex(one@goh)2> Dictionary.start_link
{:ok, #PID<0.118.0>}
iex(one@goh)3> WordlistLoader.load_from_files(~w{tasks/words/list1 tasks/words/list2})
[:ok, :ok]
iex(one@goh)4> Dictionary.anagrams_of "argon"
["ronga", "rogan", "orang", "nagor", "groan", "grano", "goran", "argon",
"angor"]
ノード two
goh@goh% iex --sname two tasks/anagrams_dist.exs
Erlang/OTP 21 [erts-10.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(two@goh)1> Node.connect :one@goh
true
iex(two@goh)2> Node.list
[:one@goh]
iex(two@goh)3> WordlistLoader.load_from_files(~w{tasks/words/list3 tasks/words/list4})
[:ok, :ok]
iex(two@goh)4> Dictionary.anagrams_of "crate"
["recta", "react", "creta", "creat", "crate", "cater", "carte", "caret"]