-module(f).
-export([curry/1]).
curry(AnonymousFun) ->
{arity, Arity} =
erlang:fun_info(AnonymousFun, arity),
do_curry(AnonymousFun, Arity, [[], [], []]).
do_curry(Fun, 0, [Fronts, Middle, Ends] = X) ->
% Fronts ++ Middle ++ ")" ++ Ends;
[F, M, E] =
lists:map(fun(L) -> string:join(L, "") end, X),
Fstring =
F ++ "Run(" ++ string:trim(M, trailing, ",") ++ ")" ++ E,
{ok, Tokens, _} =
erl_scan:string(Fstring ++ "."),
{ok, Parsed} =
erl_parse:parse_exprs(Tokens),
FunBinding =
erl_eval:add_binding(
'Run',
Fun,
erl_eval:new_bindings()
),
{value ,CurriedFun, _} =
erl_eval:exprs(Parsed, FunBinding),
CurriedFun;
do_curry(Fun, Arity, [Fronts, Middle, Ends]) ->
VarName = [64 + Arity],
NewFronts = ["fun(" ++ VarName ++ ") -> " | Fronts] ,
NewMiddle = [VarName ++ ","|Middle],
NewEnds = [" end"|Ends],
do_curry(Fun, Arity-1, [NewFronts, NewMiddle, NewEnds]).
用法(从 shell 输出中剔除的噪音):
72> c("./f") % If `f.erl` is in the current dir that is.
73> F = f:curry(fun(A,B,C) -> A + B + C end).
74> F(1).
75> G = F(1).
76> G(2).
77> H = G(2).
78> H(3).
6
79> I = (F(1))(2).
80> I(3).
6
82> F2 = mtest:curry(fun erlang:'++'/2).
83> F2("lofa").
84> (F2("lofa"))("miez").
"lofamiez"
85> ((f:curry(fun lists:map/2))((f:curry(fun filename:join/2))("dir")))(["a_file", "b_file"]).
["dir/a_file","dir/b_file"]
有用的资源: