Last active
December 18, 2015 13:49
-
-
Save zambal/5792462 to your computer and use it in GitHub Desktop.
Enum with lots of sugar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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