LoginSignup
4
2

More than 5 years have passed since last update.

ElixirのEnum.reverse() の実態は :lists.reverse/1 なので速い

Last updated at Posted at 2016-07-15

タイトルで言い切ってますが、Enum.reverse()の実態は :lists.reverse/1 です。

Erlang(結果として Elixir も)のリストは片方向リストのため、リストに値を追加する場合は、このような感じで先頭に追加して、最後に反転させるのがセオリーだそうです。

UPDATE: 例を直しました

> A = [1|[]].
> B = [2|B].
> C = [3|C].
> C.
[3,2,1]

> lists:reverse(C).
[1,2,3]

この lists:reverse/1 関数は BIF(組み込み関数)としてCで実装されているため、非常に速いようです(そのうちベンチしたい。。。)。

で、Elixir ではどうなっているのか調べてみたところ、そもそも Elixir の List モジュールには reverse に該当する関数がありません。

まさか :lists.reverse([3,2,1]) のようにして Erlang の関数を直接呼ぶ必要があるのか? と一瞬思いましたが、そんなことはありませんでした。理由は定かではありませんが、List ではなく Enum の中に Enum.reverse という関数がありました(arity は 1 と 2)。

Elixir 版もちゃんと BIF になってるのかと思い実装を見てみたところ、 lib/elixir/lib/enum.ex でこのように実装されていました。。。

 @spec reverse(t) :: list
    def reverse(enumerable) when is_list(enumerable) do
      :lists.reverse(enumerable)
    end

結局 :lists.reverse/1 を直接呼んでいるだけなので、結果として BIF で実装されていると言えます。

というわけで、リストに要素を追加する時は Erlang と同様に、先頭に要素を追加していき、最後に Enum.reverse/1 を呼べばいいということがわかりました。

4
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2