Map.new/2 uses :lists.reverse/1

While scrolling around, I found that Map.new/2 uses :lists.reverse/1 after the transformation on the enumerable is completed. I wonder if that is actually needed. I benchmarked the implementation against one without :lists.reverse/1 with benchee. The results are that it doesn’t slow down the function, but memory usage increases. I guess one reason to use :lists.reverse/1 is in order to handle duplicate keys just as Map.new/1 does. Is that the reason why :lists.reverse/1 is used?

:lists.reverse/1 is used to make sure that elements are inserted in order.

[1, 2, 2, 3, 4] |> Enum.with_index |> Map.new(&(&1))

The snippet above will cause different results between reversing the acc and not reversing it.

The pattern in new_transform is a common one when iterating over a list tail-recursively:

  • take an element from the front of the list
  • transform the element
  • prepend the element to the accumulator
  • make a recursive call

This results in the accumulator getting all the transformed results, but in reverse order.

This is the reason yes.

3 Likes