[erlang-questions] Blog: Erlang Fractal Benchmark
jm
jeffm@REDACTED
Wed Jun 6 02:44:03 CEST 2007
Mats Cronqvist wrote:
>
> so having better syntax for type guards would be a big win...
>
I've wanted optional typing in a programming language for a while now.
It seems it's either static or dynamic which leads to the whole which
approach is better war. Using the fractal code we'd have the following
code show at the end of this email. Note the static typing is limited to
one module, it's either on or off, and that the everything in the module
is statically typed meaning that static typing is not mixed with dynamic
typing, hence variables for the function signatures are all typed. Once
the first function's types have been labeled the rest could be inferred,
but why make life difficult for the compiler writers.
The notation used here is
function :: (type, type) -> type
followed by the normal erlang code. Some examples
eg1 :: (integer, float) -> float
eg1(a,b) -> a + b.
eg2 :: (integer, float) -> {float, float}
eg2 (a, b) -> {2.0 * a, 3.0 + b}.
eg3 :: (arec) -> record:arec
eg3(r) -> #arec{ a = r#arec.a + 1, b = r#arec * 2.5}.
eg4 :: (integer|float) -> float %% compound type integer|float
eg4(a) -> 2.5 * a.
Example for the record arec in eg3,
-record(arec, {a :: integer, b :: float}).
There are limitation with this typing but it's only meant for those
cases where type safety or optimisation is important. Not for use in all
code at the higher levels of a program.
Jeff.
%%%%%%%% begin example code based on fractal_benchmark
%% file: frac.erl
%% The following is NOT valid erlang code
-module(frac).
-compile(static_types).
-export([iterate/2]).
iterate :: (float, float) -> float
iterate(X, Y) ->
CR = Y - 0.5,
CI = X,
iter_value(CR, CI, 0.0, 0.0, 0.0, 0.0, 0).
iter_value :: (float, float, float, float, float, float, integer)
-> integer
iter_value(_, _, _, _, _, _, I) when I > ?MAX_ITERATIONS ->
0;
iter_value(_, _, _, ZI2, _, ZR2, I) when ZI2 + ZR2 > ?BAILOUT ->
I;
iter_value(CR, CI, ZI, ZI2, ZR, ZR2, I) ->
Temp = ZR * ZI,
ZRnew = ZR2 - ZI2 + CR,
ZInew = Temp + Temp + CI,
iter_value(CR, CI, ZInew, ZInew * ZInew, ZRnew, ZRnew * ZRnew, I + 1).
%%% file: fractal_benchmark.erl
-module(fractal_benchmark).
-author("Jim Menard, jimm@REDACTED").
-export([run/0]).
-define(BAILOUT, 16).
-define(MAX_ITERATIONS, 1000).
%% Idea from http://www.timestretch.com/FractalBenchmark.html
run() ->
io:format("Rendering~n"),
statistics(runtime),
statistics(wall_clock),
Seq = lists:seq(-39,39),
lists:foreach(fun(Y) ->
S = lists:map(fun(X) -> plot(X, Y) end, Seq),
io:format("~s~n", [S])
end, Seq),
io:format("~n"),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
Sec1 = Time1 / 1000.0,
Sec2 = Time2 / 1000.0,
io:format("Erlang Elapsed ~p (runtime) ~p (wall clock) seconds~n",
[Sec1, Sec2]).
plot(X, Y) ->
case frac:iterate(X/40.0, Y/40.0) of
0 ->
42; % ASCII for *
_ ->
32 % ASCII for space
end.
%%%% end code example
More information about the erlang-questions
mailing list