Last active
March 1, 2016 06:53
-
-
Save CarlOlson/dca7439f91d14db4075c to your computer and use it in GitHub Desktop.
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 Defs do | |
defmacro defs({name, _, _}, do: entries) | |
when length(entries) > 0 do | |
entries | |
|> Enum.map(&parse_entry(name, &1)) | |
|> Enum.map(&create_def/1) | |
|> concat_quoted | |
end | |
defmacro defps({name, _, _}, do: entries) | |
when length(entries) > 0 do | |
entries | |
|> Enum.map(&parse_entry(name, &1)) | |
|> Enum.map(&create_defp/1) | |
|> concat_quoted | |
end | |
defmacro adefs({name, _, _}, do: entries) | |
when length(entries) > 0 do | |
entries | |
|> Enum.map(&parse_entry(name, &1)) | |
|> Enum.map(&(process_anaphoric &1, name)) | |
|> Enum.map(&create_def/1) | |
|> concat_quoted | |
end | |
defp process_anaphoric({definition, body}, name) do | |
body = Macro.postwalk(body, fn | |
{:r, context, args} when is_list(args) -> | |
{name, context, args} | |
other -> other | |
end) | |
{definition, body} | |
end | |
def create_def({definition, body}) do | |
quote do | |
Kernel.def(unquote(definition)) do | |
unquote(body) | |
end | |
end | |
end | |
def create_defp({definition, body}) do | |
quote do | |
Kernel.defp(unquote(definition)) do | |
unquote(body) | |
end | |
end | |
end | |
defp parse_entry(name, {:->, _, [[{:when, _, args}], body]}) do | |
{args, [guard]} = Enum.split(args, -1) | |
definition = {:when, [], | |
[{name, [], args}, guard]} | |
{definition, body} | |
end | |
defp parse_entry(name, {:->, _, [args, body]}) do | |
definition = {name, [], args} | |
{definition, body} | |
end | |
defp concat_quoted([x | xs]), do: concat_quoted(xs, x) | |
defp concat_quoted([], acc), do: acc | |
defp concat_quoted([x | xs], acc) do | |
concat_quoted( | |
xs, | |
quote do | |
unquote(acc) | |
unquote(x) | |
end) | |
end | |
end | |
defmodule Test do | |
import Defs, only: [adefs: 2, defs: 2, defps: 2] | |
defs fib do | |
0 -> 1 | |
1 -> 1 | |
n -> fib(n - 1) + fib(n - 2) | |
end | |
def reverse(list), do: reverse(list, []) | |
defps reverse do | |
[], acc -> acc | |
[head | tail], acc -> reverse(tail, [head | acc]) | |
end | |
adefs triangle do | |
n when n <= 0 -> :error | |
1 -> 1 | |
n -> r(n - 1) + n | |
end | |
end | |
IO.write "First 10 Fibonacci numbers: " | |
0..9 | |
|> Enum.map(&Test.fib/1) | |
|> Enum.join(", ") | |
|> IO.puts | |
IO.write "1 to 10 reversed: " | |
1..10 | |
|> Enum.to_list | |
|> Test.reverse | |
|> Enum.join(", ") | |
|> IO.puts | |
IO.write "First 10 Triangular numbers: " | |
1..10 | |
|> Enum.map(&Test.triangle/1) | |
|> Enum.join(", ") | |
|> IO.puts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment