1. ホーム
  2. elixir

[解決済み] キーワードリストの利点は何ですか?

2022-10-02 23:39:25

質問

エリクサーには「地図」があります。

> map = %{:a => "one", :b => "two"} # = %{a: "one", b: "two"}
> map.a                             # = "one"
> map[:a]                           # = "one"

キーワードリストもあります。

> kl = [a: "one", b: "two"]       # = [a: "one", b: "two"]
> kl2 = [{:a, "one"},{:b, "two"}] # = [a: "one", b: "two"]
> kl == kl2                       # = true
> kl[:a]                          # = "one"
> kl.a                            # = ** (ArgumentError)

なぜ両方なのか?

シンタックス? キーワードリストにはより柔軟な構文があり、関数呼び出しの最後のパラメータとして、カールやブラケットなしで定義できるからでしょうか?それなら、なぜマップにこの構文上の糖を与えないのでしょうか?

キーの重複? Keyword Listsは重複したキーを持つことができるからでしょうか?なぜMapスタイルのアクセスと重複キーの両方を望むのでしょうか?

パフォーマンス? Keyword Listsの方が性能が良いから?それならなぜマップがあるのでしょうか?そして、マップはタプルのリストよりもキーでメンバーを探す方がパフォーマンスが高いはずではありませんか?

JSのArrayとRubyのHashのような外観? そうなんですか?

構造的に異なるデータ表現であることは理解しています。エリクサーにおけるキーワードリストは、例外的な構文(3つの異なる構文バリエーション)、マップとの重複、不明瞭な利益によって、言語を複雑にしているように思えます。

キーワードリストを使うメリットは何ですか?

どのように解決するのですか?

                   ┌──────────────┬────────────┬───────────────────────┐
                   │ Keyword List │ Map/Struct │ HashDict (deprecated) │
┌──────────────────┼──────────────┼────────────┼───────────────────────┤
│ Duplicate keys   │ yes          │ no         │ no                    │
│ Ordered          │ yes          │ no         │ no                    │
│ Pattern matching │ yes          │ yes        │ no                    │
│ Performance¹     │ —            │ —          │ —                     │
│ ├ Insert         │ very fast²   │ fast³      │ fast⁴                 │
│ └ Access         │ slow⁵        │ fast³      │ fast⁴                 │
└──────────────────┴──────────────┴────────────┴───────────────────────┘

キーワードリストは軽量で、その下にシンプルな構造を持っているので、とても柔軟です。Erlangの規約の上にあるシンタックスシュガーと考えることができ、あまり醜いコードを書かずにErlangとのインタフェースを簡単にすることができます。例えば、キーワードリストは関数の引数を表すのに使われますが、これはErlangから受け継いだ性質です。特に重複するキーや順序が必要な場合、キーワードリストが唯一の選択肢になることがあります。キーワードリストは他の選択肢とは異なる性質を持っていて、ある状況にはより適していますが、他の状況にはあまり適していません。

マップ (および構造体) はハッシュベースの実装を持つため、実際のペイロードデータを格納するために使用されます。キーワード リストは、内部的には各操作ごとに走査される必要がある単なるリストなので、定時間アクセスのような古典的なキーバリュー データ構造の特性は持っていません。

Elixirはまた HashDict の回避策として が書かれた当時は、マップのパフォーマンスの悪さを回避するために . しかし、これはElixir 1.0.5/Erlang 18.0では修正されており、また HashDict は将来のバージョンでは非推奨となります。 .

Erlangの標準ライブラリを深く掘り下げると、キーと値のペアを格納するデータ構造がさらにたくさんあります。

複数のプロセスおよび/またはVMにまたがってキー/値のペアを保存する必要がある場合にも、これらのオプションがあります。


¹ 一般的にはそうですが、もちろん によります。 ™.

² 最も良いケースは、リストへのプリペンドだけです。

³ Elixir 1.0.5 以降に適用されます。古いバージョンでは遅くなる可能性があります。

HashDict は現在非推奨となっています。

⁵ 平均して要素の半分をスキャンする線形探索を必要とします。