Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Elixir-like pipe in Erlang
-module(pipe).
-compile(export_all).
parse_transform(Forms, Options) ->
Forms2 = replace(Forms),
io: format("~p~n", [Forms2]),
Forms2.
replace({lc, Line, {atom, Line2, '|>'}, Path}) ->
pipe(Path);
replace({lc, Line, {atom, Line2, pipe}, Path}) ->
pipe(Path);
replace(Forms) when is_list(Forms) ->
[replace(F) || F <- Forms];
replace(Forms) when is_tuple(Forms) ->
Forms2 = tuple_to_list(Forms),
Forms3 = [replace(F) || F <- Forms2],
list_to_tuple(Forms3);
replace(Form) ->
Form.
pipe([A|T]) ->
mkfun(T, A).
mkfun([], A) ->
A;
% {m, f, ...}
mkfun([{tuple, Line, [M, F | A0]}|T], A) ->
mkfun(T, {call, Line, {remote, Line, M, F}, [A|A0]});
% m:f
mkfun([{remote, Line, M, F}|T], A) ->
mkfun(T, {call, Line, {remote, Line, M, F}, [A]});
% m:f(...)
mkfun([{call, Line, Remote, A0}|T], A) ->
mkfun(T, {call, Line, Remote, [A|A0]});
% f
mkfun([{atom, Line, F}|T], A) ->
mkfun(T, {call, Line, {atom, Line, F}, [A]}).
-module(test).
-compile(export_all).
-compile({parse_transform, pipe}).
% [pipe||Arg, ...]
% Arg (first element) is passed as is, the rest are transformed into function calls
% Arg and every call result become first argument of the next call:
% [pipe||x, fn(y)] => fn(x, y)
% [pipe||x, fn(y), fn(z)] => fn(fn(x, y), z)
% Functions are called from left to right
test() ->
A = 1,
[pipe||A, fn, fn, fn]. % fn(fn(fn(A)))
test2() ->
[pipe||foo, md:fn, md:fn(1,2), fn]. % fn(md:fn(md:fn(foo),1,2))
test3() ->
['|>'||foo, {md,fn}, {md,fn,1,2}, fn]. % fn(md:fn(md:fn(foo),1,2))
fn(A) -> A + 1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.