Skip to content

Instantly share code, notes, and snippets.

@benjamintanweihao
Created July 13, 2016 06:12
Show Gist options
  • Select an option

  • Save benjamintanweihao/4f5f62ce32b7947ddec6cf598667bfd3 to your computer and use it in GitHub Desktop.

Select an option

Save benjamintanweihao/4f5f62ce32b7947ddec6cf598667bfd3 to your computer and use it in GitHub Desktop.
defmodule MacroPlayground do
defmacro para(ast) do
# 0. Store the pid of the current process
me = self
pids = Macro.prewalk(ast, fn
# 1. Pattern matching can be done with function arguments!
{:for, meta, args} ->
# 2. Extract the do block of the comprehension
[do: do_block] = args |> List.last
# 3. Wrap the do block around a spawn. Send the result to the
# current process.
spawn_do_block = quote do
spawn(fn -> send(unquote(me), {self, unquote(do_block)}) end)
end
# 4. Swap out the `do_block` (the last element of `args`)
# with the `spawn_do_block`
{:for, meta, List.replace_at(args, -1, [do: spawn_do_block])}
# 5. We just output the same node for any other node
node ->
node
end)
quote do
unquote(pids)
|> Enum.map(fn pid ->
receive do
{^pid, result} ->
result
end
end)
end
end
end
defmodule Foo do
import MacroPlayground
def foo do
x = para(for a <- 1..10,
b <- 1..10,
c <- 1..10,
a + b + c <= 10000,
do: {a, b, c})
IO.inspect x
end
end
Foo.foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment