I'm doing some excises based on the 99-Problems list. For P01 which purpose is to find the last element of a list, my implementation is almost always outperformed by List.last/1 while being the same. The difference is about 20% but there is quite a lot of variations between executions (sometimes more than 100%). Tests are done on a freshly restarted VM and functions are called 10, 100 and 1000 on a list of one million elements.
This is my implementation:
def p01([]), do: nil
def p01([h]), do: h
def p01([_ | r]), do: p01(r)
A closer look at List.last/1 source shows however 2 differences
@compile :inline_list_funcs which I understand being an Erlang directive only applying on the current module. I'm not sure if it has a real impact on my short piece of code@spec last([elem]) :: nil | elem when elem: varThese two changes made the execution times of my implementation closer much more often to the ones of List.last/1.
Q1: Does the compiler use @spec... to optimize the code somehow ?
Q2: side question : in my tests, the erlang standard library function :lists.last/1 does always better than List.last/1. Again there are are some variations between two runs but the difference is quite stable. Why isn't List.last/1 a simple wrapper around the Erlang implementation ?
I am not sure about question #2, but re: question #1, from the elixir docs: "type specifications are never used by the compiler to optimize or modify code", see: https://hexdocs.pm/elixir/typespecs.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With