Archaelus在这篇文章中建议写一个新的格式例程来处理命名参数可能是一个很好的学习练习.因此,本着学习语言的精神,我编写了一个处理命名参数的格式化例程.
一个例子:
1> fout:format("hello ~s{name}, ~p{one}, ~p{two}, ~p{three}~n",[{one,1},{three,3},{name,"Mike"},{two,2}]). hello Mike, 1, 2, 3 ok
基准:
1> timer:tc(fout,benchmark_format_overhead,["hello ~s{name}, ~p{one}, ~p{two}, ~p{three}~n",[{one,1},{name,"Mike"},{three,3},{two,2}],100000]). {421000,true} = 4.21us per call
虽然我怀疑这个开销大部分是由于循环,但是调用带有一个循环的函数会产生<1us的响应.
1> timer:tc(fout,benchmark_format_overhead,["hello ~s{name}, ~p{one}, ~p{two}, ~p{three}~n",[{one,1},{name,"Mike"},{three,3},{two,2}],1]). {1,true}
如果有更好的方法在erlang中进行基准测试,请告诉我.
守则:(
根据道格的建议修订)
-module(fout). -export([format/2,benchmark_format_overhead/3]). benchmark_format_overhead(_,_,0)-> true; benchmark_format_overhead(OString,OList,Loops) -> {FString,FNames}=parse_string(OString,ONames), benchmark_format_overhead(OString,OList,Loops-1). format(OString,ONames) -> {FString,FNames}=parse_string(OString,ONames), io:format(FString,FNames). parse_string(FormatString,Names) -> {F,N}=parse_format(FormatString), {F,substitute_names(N,Names)}. parse_format(FS) -> parse_format(FS,"",[],""). parse_format("",FormatString,ParamList,"")-> {lists:reverse(FormatString),lists:reverse(ParamList)}; parse_format([${|FS],FormatString,ParamList,"")-> parse_name(FS,FormatString,ParamList,""); parse_format([$}|_FS],FormatString,_,_) -> throw({'unmatched } found',lists:reverse(FormatString)}); parse_format([C|FS],FormatString,ParamList,"") -> parse_format(FS,[C|FormatString],ParamList,""). parse_name([$}|FS],FormatString,ParamList,ParamName) -> parse_format(FS,FormatString,[list_to_atom(lists:reverse(ParamName))|ParamList],""); parse_name([${|_FS],FormatString,_,_) -> throw({'additional { found',lists:reverse(FormatString)}); parse_name([C|FS],FormatString,ParamList,ParamName) -> parse_name(FS,FormatString,ParamList,[C|ParamName]). substitute_names(Positioned,Values) -> lists:map(fun(CN)-> case lists:keysearch(CN,1,Values) of false -> throw({'named parameter not found',CN,Values}); {_,{_,V}} -> V end end, Positioned).
由于这是一次学习练习,我希望那些对erlang更有经验的人可以给我提示如何改进我的代码.
干杯,迈克