Hello, I was wondering as there is no while loop in elixir, how would that look like written in Elixir:
while exists (s, m, sn) ∈ pending such that sn = next[s] do
next[s] := next[s]+1;
pending := pending \ {(s, m, sn)};
I do not really get what that algorithm does. To me it seems like you have some problem with transcription of the original one.
pending is a set of processes, next is an Array
Ahh, ok. Now I get. I can take a look later when I will be near computer
Generally you would turn the while loop into an Enum.reduce and the variables that you would have mutated get passed as part of the accumulator.
This appears to be a fragment from Algorithm 3.12 in “Introduction to Reliable and Secure Distributed Programming”.
Folks will be able to answer this question a lot more effectively if they have that context.
In that algorithm, pending is a set of tuples {sender, message, sequence_number} while next is a map from sender to the next sequence_number expected from that sender.
The while loop finds {sender, message_to_deliver, sequence_number} values in pending, and does three things:
- increments
nextforsender - removes the tuple from
pending - delivers
message_to_deliverfromsender
Something like this would be my attempt:
pending = [
{1, "hello1", 2},
{1, "hello2", 1},
{2, "hello3", 1},
{2, "hello4", 2},
{2, "hello5", 4}
]
next = %{
1 => 1,
2 => 1
}
pending_transformed =
for {sender, message, sn} <- pending,
into: %{},
do: {{sender, sn}, message}
{pending_transformed, next}
|> Stream.unfold(fn
nil ->
nil
{pending_transformed, next} ->
result =
pending_transformed
|> Map.keys
|> Enum.find(fn {sender, sn} -> next[sender] == sn end)
case result do
{sender, sn} = key ->
{message, pending_transformed} = Map.pop!(pending_transformed, key)
next = Map.put(next, sender, sn + 1)
{{:send, {sender, message, sn}}, {pending_transformed, next}}
nil ->
{{:done, {pending_transformed, next}}, nil}
end
end)
|> Enum.reduce_while([], fn
{:send, msg}, acc ->
IO.inspect(msg)
{:cont, acc}
{:done, rest}, _ ->
{:halt, rest}
end)
# Output
{1, "hello2", 1}
{1, "hello1", 2}
{2, "hello3", 1}
{2, "hello4", 2}
# Result
{%{{2, 4} => "hello5"}, %{1 => 3, 2 => 3}}
Do you by any chance have that algorithm in code version ?






















