Archaelus schlug in this post vor, dass das Schreiben einer neuen Format-Routine, um benannte Parameter zu behandeln, eine gute Lernübung sein kann. Also habe ich im Geiste des Erlernens der Sprache eine Formatierungsroutine geschrieben, die benannte Parameter behandelt.Drucken benannter Parameter
Ein Beispiel:
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
Die Benchmark:
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
Obwohl ich vermute, th Ein Großteil dieses Overheads ist auf Schleifen zurückzuführen, da ein Aufruf der Funktion mit einer Schleife eine Antwort in < 1us ergibt.
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}
Wenn es einen besseren Weg zum Benchmarking in Erlang gibt, lass es mich wissen.
Der Code: Ich hatte gehofft, eine Lernübung,
-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).
Da dies (die mit Doug Vorschlag entsprechend überarbeitet wurde), dass diejenigen, erfahreneren mit erlang mir geben könnte Tipps, wie ich meinen Code verbessern kann.
Cheers, Mike
Für Timing-Zwecke, wenn es zu schnell ist, um zu messen, sollten Sie es in einer Schleife ausführen und den Durchschnitt als die Zeit nehmen –
Bitte umformulieren Sie Ihre Frage im Titel, ich würde nicht wissen, was Sie gefragt haben, wenn ich sah es in den Suchergebnissen. – Soviut