Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use erlang lists:map function

Tags:

erlang

The following is a erlang function. I don't understand how lists:map function is used here. Could someone please explain?

% perform M runs with N calls to F in each run.
% For each of the M runs, determine the average time per call.
% Return, the average and standard deviation of these M results.

time_it(F, N, M) ->
      G = fun() -> F(), ok end,
      NN = lists:seq(1, N),
      MM = lists:seq(1, M),
      T = lists:map(
            fun(_) ->
          T0 = now(),               % start timer
          [ G() || _ <- NN ],           % make N calls to F
          1.0e-6*timer:now_diff(now(), T0)/N    % average time per call
        end,
        MM
          ),
      { avg(T), std(T) }.

Thanks.

also, I don't know the proper syntax when using this function. For example, I have a dummy() function take 1 parameter. I get an error while trying to time the dummy function.

moduleName:time_it(moduleName:dummy/1, 10, 100).

the above would evaluate to illegal expression.

Actually, now with the correct syntax, the function can be invoked correctly with:

moduleName:time_it(fun moduleName:dummy/1, 10, 100).

However, it will throw a exception saying invoking dummy function without passing any parameter. I think this line is the villain, [ G() || _ <- NN ], I have no idea how to fix it.

like image 608
Quincy Avatar asked Oct 10 '09 23:10

Quincy


2 Answers

map is used here to execute the function

T0 = now(),                           % start timer
[ G() || _ <- NN ],                   % make N calls to F
1.0e-6*timer:now_diff(now(), T0)/N    % average time per call

for each element of MM. map will return a new list of the same size, where each element of the new list is the result of applying the above function to the corresponding element of MM.

You can invoke time_it like:

moduleName:time_it(fun moduleName:dummy/1, 10, 100).
like image 62
sepp2k Avatar answered Nov 16 '22 01:11

sepp2k


The purpose of lists:map in the time_it function is just to run the inner function M times. When you see this pattern:

L = lists:seq(1,M),
lists:map(fun(_)-> Foo() end, L)

It just means call Foo() again and again M times, and return the results of each call in a list. It actually makes a list of integers [1,2,3,...N] and then calls Foo() once for each member of the list.
The author of time_it does this same trick again, because time_it needs to call the function you give it N*M times. So inside the outer loop that runs M times they use a different technique to run the inner loop N times:

L = lists:seq(1,N),
[Foo() || _ <- L]

This has exactly the same result as the code above, but this time Foo is called N times.

The reason you are having trouble using time_it with your dummy function is that time_it takes a function with 0 parameters, not 1. So you need to make a dummy function and call it like this:

dummy() -> 
    %% do something here you want to measure
    ok.

measure_dummy() ->
    time_it(fun someModule:dummy/0, 10, 100).
like image 38
Rob Charlton Avatar answered Nov 16 '22 03:11

Rob Charlton