raich
raich

Reputation: 127

Erlang:creating list of tuples within lists:foreach

I query the list of users from Mnesia Database in Chicagoboss. I'm getting the error when I try to add the Lists within lists:foreach with ++ operator. My aim is, based on userid I will do ets:lookup to my cache and create a List like - [{{<<"name">>,<<"Batman">>}, {<<"steps">>,2552}, {<<"distance">>,2050}}].

For each user I'll create this list and add with the previous List. So that ultimately I can can sort on <<"steps">> and convert the binary list by json encoding and send it to the client via Websockets.

I'm getting the error at this line: Reading1 = Reading2 ++ Currentlist

as I've decalred Reading1 as an Empty list.

My question is how can I manipulate the lists within the lists:foreach and then send the result List via websocket?

        BelugaUsers = boss_db:find(users, [{accesstoken, 'not_equals', ''}]),
        Reading1 = [],
        Reading2 = [],
        lists:foreach(fun(X) ->         
        {_,_,BEmail,BName,_,_,BAccessToken,_} = X,
        UserKey = BEmail ++ "-" ++ ?MYAPICALL1,
        io:format("UserKey for Leader Board: ~n~p~n",[UserKey]),
        [Reading] = ets:lookup(myapi_cache, list_to_binary(UserKey)),
        {_,Result} = Reading,

        ActivitySummary = proplists:get_value(<<"activitySummary">>, Result),
        %Print ActivitySummary for the user ....printing fine 
        io:format("ActivitySummary ==========: ~n~p~n",[ActivitySummary]),

        %Create a list of the format
        %[{{<<"name">>,<<"Batman">>}, {<<"steps">>,2552}, {<<"distance">>,2050}}]

        Currentlist = [{{<<"name">>, list_to_binary(BName)}, {<<"steps">>, proplists:get_value(<<"steps">>, ActivitySummary)}, {<<"distance">>, proplists:get_value(<<"distance">>, ActivitySummary)}}],
        %% HERE I'M GETTING error%%
        Reading1 = Reading2 ++ Currentlist
        end, BelugaUsers),
        %sort the list
        Reading3 = lists:keysort(2, Reading1),
        %reverse the list
        Reading4 = lists:reverse(Reading3),
        WebSocketId ! {text, jsx:encode(Reading4)},

Upvotes: 1

Views: 432

Answers (1)

Steve Vinoski
Steve Vinoski

Reputation: 20014

Erlang variables are single-assignment; once bound to a value, they can't be re-bound to a different value.

The lists:foreach/2 function is not useful for this problem because it can't create a new value and return it to its caller. You should instead use lists:map/2, perhaps like this:

BelugaUsers = boss_db:find(users, [{accesstoken, 'not_equals', ''}]),
Reading = lists:map(
            fun(X) ->
                    {_,_,BEmail,BName,_,_,BAccessToken,_} = X,
                    UserKey = BEmail ++ "-" ++ ?MYAPICALL1,
                    io:format("UserKey for Leader Board: ~n~p~n",[UserKey]),
                    {_,Result} = hd(ets:lookup(myapi_cache, list_to_binary(UserKey))),

                    ActivitySummary = proplists:get_value(<<"activitySummary">>, Result),
                    %%Print ActivitySummary for the user ....printing fine
                    io:format("ActivitySummary ==========: ~n~p~n",[ActivitySummary]),

                    %%Create a tuple of the format
                    %%{{<<"name">>,<<"Batman">>}, {<<"steps">>,2552}, {<<"distance">>,2050}}
                    {{<<"name">>, list_to_binary(BName)},
                     {<<"steps">>, proplists:get_value(<<"steps">>, ActivitySummary)},
                     {<<"distance">>, proplists:get_value(<<"distance">>, ActivitySummary)}}
            end, BelugaUsers),
%%sort the list
Reading2 = lists:keysort(2, Reading),
%%reverse the list
Reading3 = lists:reverse(Reading2),
WebSocketId ! {text, jsx:encode(Reading3)}.

The lists:map/2 function applies a function to each value in a list to a produce a potentially different value and returns a new list consisting of those new values. This is essentially what you were trying to do with lists:foreach/2 and your attempt to use imperative assignment to add each element to an already-existing list.

You could alternatively use a list comprehension but I think lists:map/2 is clearer in this situation.

Upvotes: 3

Related Questions