@ patrick-oscity eine wirklich gründliche Antwort gegeben hat, und ich mag es sehr. Ich bin jedoch mit einer Version gegangen, die dies nur mit dem Mustervergleich mit dem Pin-Operator tun kann.
Für Kontext, ich schreibe einen Akku, der die Ergebnisse aller seiner Eingaben an einen Aktor weiterleitet, wenn alle Eingänge empfangen wurden.Ich möchte auch, dass die akkumulierte Ausgabe, die eine Liste ist, eine vordefinierte Reihenfolge der Prozesse einhält, die ursprünglich ihre Ausgaben gesendet haben.
Danach beginnt der Akku wieder auf Nachrichten zu warten.
Der Akkumulator sieht wie folgt aus:
def start_link(actuator, actuator_pid) do
Task.start_link(fn -> loop(actuator, actuator_pid, actuator.inputs, []) end)
end
defp loop(actuator, actuator_pid, [], acc) do
result = acc |> Enum.reverse
send actuator_pid, {:forward, self(), result}
loop(actuator, actuator_pid, actuator.inputs, [])
end
defp loop(actuator, actuator_pid, [input | remaining_inputs], acc) do
receive do
{:forward, ^input, output} ->
loop(actuator, actuator_pid, remaining_inputs, [output | acc])
end
end
Um zu beweisen, es tut, was ich will, denn dies ist die Tests sind wie folgt:
test "When I recieve the outputs from all my inputs, then I return the accumulated result in the order of my actuator's inputs" do
{_, pid0} = Task.start_link(fn -> test_loop end)
{_, pid1} = Task.start_link(fn -> test_loop end)
{_, pid2} = Task.start_link(fn -> test_loop end)
actuator = %Cerebrum.Actuator{
inputs: [pid0, pid1, pid2]
}
actuator_pid = self()
{_, pid} = start_link(actuator, actuator_pid)
send pid, {:forward, pid0, 0}
refute_receive {:forward, pid, [0]}
send pid, {:forward, pid1, 1}
refute_receive {:forward, pid, [0, 1]}
send pid, {:forward, pid2, 2}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid0, 0}
send pid, {:forward, pid1, 1}
send pid, {:forward, pid2, 2}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid0, 0}
send pid, {:forward, pid2, 2}
send pid, {:forward, pid1, 1}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid1, 1}
send pid, {:forward, pid0, 0}
send pid, {:forward, pid2, 2}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid1, 1}
send pid, {:forward, pid2, 2}
send pid, {:forward, pid0, 0}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid2, 2}
send pid, {:forward, pid1, 1}
send pid, {:forward, pid0, 0}
assert_receive {:forward, pid, [0, 1, 2]}
send pid, {:forward, pid2, 2}
send pid, {:forward, pid1, 1}
send pid, {:forward, pid0, 0}
assert_receive {:forward, pid, [0, 1, 2]}
end
defp test_loop do
test_loop
end
Dank für die eingehende Antwort. Ich bin mit einer anderen Version gegangen, die einen geraden Patten-Abgleich verwendet. Aber weil es so interessant war, werde ich deine Antwort als richtig markieren. –