Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Parse transform to add partial application to erlang
-module(pt).
-export([parse_transform/2]).
parse_transform(ASTIn, _Options) ->
format(ASTIn).
format({call, Line, {atom, _, FName}, FixedArgs} = Call) ->
case handle_partial_application(FName, Line) of
undefined ->
format_tuple(Call);
{FCall, Arity} ->
Args = [{var, Line, N} ||
N <- lists:seq(1, Arity - length(FixedArgs))],
R = {'fun', Line, {clauses, [{clause, Line, Args, [],
[{call, Line, FCall,
format(FixedArgs) ++ Args}]}]}},
format(R);
_A ->
format_tuple(Call)
end;
format(Tuple) when is_tuple(Tuple) ->
format_tuple(Tuple);
format(List) when is_list(List) ->
[format(X) || X <- List];
format(Any) ->
Any.
format_tuple(Tuple) ->
list_to_tuple([format(X) || X <- tuple_to_list(Tuple)]).
handle_partial_application(FName, Line) ->
FNameStr = atom_to_list(FName),
case erl_scan:string(FNameStr) of
{ok, [{atom, _, OrigFName}, {'/', _}, {integer, _, Arity}], _} ->
{{atom, Line, OrigFName}, Arity};
{ok, [{atom, _, Module}, {':', _}, {atom, 1, OrigFName},
{'/', _}, {integer, _, Arity}], _} ->
{{remote, Line, {atom, Line, Module}, {atom, Line, OrigFName}}, Arity};
_ ->
undefined
end.
@HernanRivasAcosta

This comment has been minimized.

Copy link
Owner Author

@HernanRivasAcosta HernanRivasAcosta commented Oct 15, 2014

-module(pt_test).

-compile({parse_transform, pt}).

-export([test_it/0, send/2]).

send(Message, Target) ->
    io:format("Hey ~p! You got a new message: ~p~n", [Target, Message]).

test_it() ->
    F = 'send/2'("Is this cool enough?"),
    F("Mr. User").
@HernanRivasAcosta

This comment has been minimized.

Copy link
Owner Author

@HernanRivasAcosta HernanRivasAcosta commented Oct 15, 2014

Thanks @elbrujohalcon for pointing out I forgot about remote calls.

Now this works:

lists:map('io:format/2'("~p~n"), [["a line"],["another line"],["oh my gawd!"]]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment