Skip to content

Instantly share code, notes, and snippets.

@zambal
Last active December 18, 2015 13:49
Show Gist options
  • Save zambal/5792462 to your computer and use it in GitHub Desktop.
Save zambal/5792462 to your computer and use it in GitHub Desktop.
Enum with lots of sugar
defmodule Enex do
defmacro map enum, clauses do
fnc = {:fn, [], [clauses]}
quote do: Enum.map(unquote(enum), unquote(fnc))
end
defmacro reduce enum, acc, clauses do
fnc = {:fn, [], [clauses]}
quote do: Enum.reduce(unquote(enum), unquote(acc), unquote(fnc))
end
@skip :"__FMAP^SKIP__"
defmacro fmap enum, clauses do
{:"->", meta, forms} = clauses[:do]
skip_clause = {[{:_, [], nil}], @skip}
clauses = [do: {:"->", meta, forms ++ [skip_clause]}]
fnc = {:fn, [], [clauses]}
fmap_quote(enum, fnc)
end
defmacro freduce enum, acc, clauses do
{:"->", meta, forms} = clauses[:do]
skip_clause = {[{:_, [], nil}, {:_, [], nil}], @skip}
clauses = [do: {:"->", meta, forms ++ [skip_clause]}]
fnc = {:fn, [], [clauses]}
freduce_quote(enum, fnc, acc)
end
defmacro select head, opts, block // [] do
match =
case head do
{:when, _, [m|_]} -> m
_ -> head
end
enum = opts[:from]
do_block = block[:do] || opts[:do] || match
select_clause = {[head], do_block}
skip_clause = {[{:_, [], nil}], @skip}
clauses = [do: {:"->", [], [select_clause, skip_clause]}]
fnc = {:fn, [], [clauses]}
fmap_quote(enum, fnc)
end
defp fmap_quote enum, fnc do
quote do
pick =
fn(x, acc) ->
case unquote(fnc).(x) do
unquote(@skip) -> acc
x -> [x|acc]
end
end
Enum.reduce(unquote(enum), [], pick)
|> Enum.reverse
end
end
defp freduce_quote enum, fnc, acc do
quote do
pick =
fn(x, acc) ->
case unquote(fnc).(x, acc) do
unquote(@skip) -> acc
new_acc -> new_acc
end
end
Enum.reduce(unquote(enum), unquote(acc), pick)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment