以下が確認済み。
- Universe.Supervisor
- Universe
続き、は Cell.Supervisor ですかね。
Cell の実装
- 初期化コールバックにて Cell を子プロセスとして管理するよう登録
- chidren と positions という API の定義
children の定義が以下です。
# Return the PIDs of the children processes
def children do
Cell.Supervisor
|> Supervisor.which_children
|> Enum.map(fn {_, pid, _, _} -> pid end)
end
コメントにある通り、pid なリストを戻している風なのですが
- Cell.Supervisor が何を戻すのか
- which_children という手続きについて
というあたりが微妙に謎。
ええと
which_children は Supervisor の pid を引数に取る、とのことで Cell.Supervisor
は自身の pid を戻すのですかね。や、[{Id, Child, Type, Modules}]
という記載がありますね成程。
あるいは positions
定義が以下です。
# Return the positions {x: a, y: b} of the children processes
def positions do
children()
|> Enum.map(&Cell.info/1)
|> Enum.map(fn {x, y, n} -> %{x: x, y: y, n: n} end)
end
Cell.info な定義は
# Return info about a Cell (number of neighbours
# and coordinates)
def info(process) do
GenServer.call(process, {:info})
end
となっており、実体は以下。
# Return info about the cell: {x, y, number_of_neighbours}
def handle_call({:info}, _from, position) do
{:reply, Tuple.append(position, do_count_neighbours(position)), position}
end
# Count the living neighbours of a Cell
defp do_count_neighbours(position) do
position
|> neighbouring_positions
|> keep_live
|> length
end
do_count_neighbours も面白そうです。パイプラインな手続きが以下なのですが
# Compute the coordinates of the eight neighbouring
# positions of a Cell at {x, y}
defp neighbouring_positions({x, y}) do
@offsets
|> map(fn {dx, dy} -> {x + dx, y + dy} end)
end
# Determine which Cells to are alive
defp keep_live(positions) do
filter(positions, &(lookup(&1) != nil))
end
@offsets
は隣接セルとのオフセットな配列になってます。neighbouring_positions で位置を取得して keep_live でその Cell の生死を判断するために生きてる Cell をフィルタしてそのリストの length を戻しているのか成程。つうか lookup て何かというと以下でした。
# Translate the Cell position {x, y} into the process
# ID if the Cell is alive (avoid ghost neighbours)
def lookup(position) do
Cell.Registry
|> Registry.lookup(position)
|> Enum.map(fn
{pid, _valid} -> pid
nil -> nil
end)
|> Enum.filter(&Process.alive?/1)
|> List.first
end
これ、何となくそれぞれが戻すのがリストなので、という事に見えますね。単純に引数で渡された position が Cell として有効な状態なのであればその pid を戻す、という記述に見えます。
なので
Cell.Supervisor.positions については位置情報と有効な Cell の hash な配列が戻る、という理解で良いのかしら。
そろそろ
テスツ書きたくなってきました。OTP な試験について確認入れてみます。