Skip to content

Instantly share code, notes, and snippets.

@doomspork
Last active February 24, 2016 22:22
Show Gist options
  • Save doomspork/8f0d72dc1373f5a7448d to your computer and use it in GitHub Desktop.
Save doomspork/8f0d72dc1373f5a7448d to your computer and use it in GitHub Desktop.
defmodule Concoct do
@alphabet "abcdefghijklmnopqrstuvwxyx"
@reserved ~w(init module_info)a
defmacro __using__(mod, _opts \\ []) do
wrappers = mod.module_info
|> Keyword.get(:exports)
|> Enum.filter(&Concoct.reserved_fun/1)
|> Enum.map(&Concoct.wrap_erl_fun/1)
quote do
@erl_mod unquote(mod)
unquote_splicing(wrappers)
end
end
def reserved_fun({name, _arity}) when name in @reserved do
false
end
def reserved_fun(_), do: true
def wrap_erl_fun({name, arity}) do
arity = if arity == 0, do: 0, else: arity - 1
args = Enum.map(0..arity, &Concoct.gen_arg_name/1)
[sub|rem] = args
erl_args = rem ++ [sub]
quote do
def unquote(name)(unquote_splicing(args)) do
@erl_mod.unquote(name)(unquote_splicing(erl_args))
end
end
end
def gen_arg_name(count) when count <= 25 do
atom = @alphabet
|> String.at(count)
|> String.to_atom
{atom, [], Elixir}
end
def gen_arg_name(count) do
count
|> Integer.to_string
|> String.split("", trim: true)
|> Enum.map(&Concoct.gen_arg_name/1)
|> Enum.join
end
end
defmodule ConcoctTest do
use ExUnit.Case
doctest Concoct
defmodule Queue do
use Concoct, :queue
end
setup do
queue = :queue.new
{:ok, %{queue: queue}}
end
test "wraps simple functions", %{queue: queue} do
assert Queue.len(queue) == 0
end
test "moves subject for Elixir piping", %{queue: queue} do
len = queue
|> Queue.in("Hi")
|> Queue.len
assert len == 1
end
end
@koudelka
Copy link

i can has plz ;_;

defmodule ErlangPipe do
  # <~> is apparently an unused operator at the moment?
  defmacro from <~> to do
    {mf, context, args} = to
    {mf, context, args ++ [from]}
  end
end
iex> :queue.new <~> :queue.in("a") <~> :queue.in("b") <~> :queue.to_list
["a", "b"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment