Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does erlang have a hidden rownum on a list?

Tags:

erlang

This is an example of my current code:

DataSet = [1,2,3,4,5,6,7,8,9].

Sequence = [3,4,5,6].

ReducedDataSet = lists:foldl( fun(SeqNumber, Output) ->
                                 Row = lists:nth(SeqNumber, DataSet),
                                 [Row|Output]
                              end,
                              [],
                              Sequence
                             ).

ReducedDataSet ends up as [6,5,4,3] and if I change it to lists:foldr, ReducedDataSet would be [3,4,5,6].

I didn't expect this as when absorbed left to right, the 3rd value is 3 and should proceed to 6, but when absorbed right to left, the 3rd value would be 7, and proceed to 4.

Does this mean there's a hidden row number on my list, and foldl and foldr only differ in the sort order of the final list?

like image 834
Philbo Avatar asked Mar 08 '23 02:03

Philbo


2 Answers

I think this is a more general fold question.

In general, fold performs the following: (new_element, acc) -> new_acc

If the operation new_element ° acc is commutative (e.g. the sum), foldl and foldr are the same.

If the operation is "append" there is a difference between appending the element to the left or to the right.

[3] ° 4 -> [3, 4] VS 4 ° [3] -> [4, 3]

I never remember which is foldl and foldr but I think left/right refers to the position of the accumulator ([3] ° 4 is foldl with this definition)

like image 111
pazqo Avatar answered Mar 15 '23 19:03

pazqo


TL;DR

No, there is no hidden index or "row number" in an Erlang list.

Discussion

It may be helpful to explore the nature of list operations a bit more in the context of functional lists of the "lists are a bunch of conses" variety.

I wrote an explanation of folds a while back that might be useful to you: Explanation of lists:fold function

Keep in mind that functional lists only have pointers that go one-way. That is, they are singly linked lists. There is no concept of a "rownum" or "index" as it would be in a C style array. Each call to lists:nth/2 is actually traversing the list to the nth element before returning that element.

We could write lists:nth/2 like this if we want a version that crashes on bad input (and, looking it up, it turns out that it is written almost exactly like this):

nth(1, [Element | _]) ->
    Element;
nth(N, [_ | Rest]) when N > 1 ->
    lists:nth(N - 1, Rest).

(As a side note, consider not inlining funs that require you to write multi-line definitions as function arguments...)

like image 43
zxq9 Avatar answered Mar 15 '23 21:03

zxq9