Skip to content

Instantly share code, notes, and snippets.

@ToJans
Last active December 31, 2015 05:39
Show Gist options
  • Save ToJans/7941956 to your computer and use it in GitHub Desktop.
Save ToJans/7941956 to your computer and use it in GitHub Desktop.
Enumerable elixir continuations
// José's proposition
{ :suspended, n_, cont } = Enumerable.reduce(1..5, { :cont, 0 }, fn x, n ->
if x == 3 do
{ :suspend, n }
else
{ :cont, n + x }
end
end)
defmodule Interleave do
def interleave(a, b) do
step = fn x, acc -> { :suspend, [x|acc] } end
af = &Enumerable.reduce(a, &1, step)
bf = &Enumerable.reduce(b, &1, step)
do_interleave(af, bf, []) |> :lists.reverse()
end
defp do_interleave(a, b, acc) do
case a.({ :cont, acc }) do
{ :suspended, acc, a } ->
case b.({ :cont, acc }) do
{ :suspended, acc, b } ->
do_interleave(a, b, acc)
{ :halt, acc } ->
acc
{ :done, acc } ->
finish_interleave(a, acc)
end
{ :halt, acc } ->
acc
{ :done, acc } ->
finish_interleave(b, acc)
end
end
defp finish_interleave(a_or_b, acc) do
case a_or_b.({ :cont, acc }) do
{ :suspended, acc, a_or_b } ->
finish_interleave(a_or_b, acc)
{ _, acc } ->
acc
end
end
end
Interleave.interleave([1,2], [:a, :b, :c, :d])
#=> [1, :a, 2, :b, :c, :d]
defmodule Interleave do
def interleave(a, b, acc//[]) do
if (Enum.any?(a) && Enum.any?(b)) do
interleave Enum.drop(a, 1),Enum.drop(b, 1), [Enum.first(b) | [Enum.first(a) | acc]]
else
acc |> :lists.reverse |> Enum.concat(a) |> Enum.concat(b)
end
end
end
Interleave.interleave([1,2], [:a, :b, :c, :d])
#=> [1, :a, 2, :b, :c, :d]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment