Anahtar Kelime Listelerinin faydası nedir?


101

İksirde Haritalarımız var:

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

Ayrıca Anahtar Kelime Listelerimiz de var:

> 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)

Neden ikisi birden?

Sözdizimi? Bunun nedeni, Anahtar Sözcük Listelerinin kıvrımsız ve hatta bir işlev çağrısının son parametresi olarak köşeli parantezler olmadan tanımlanmalarına izin veren daha esnek bir sözdizimine sahip olması mıdır? Öyleyse neden Haritalar'a bu sözdizimsel şekeri vermiyorsunuz?

Yinelenen Anahtarlar? Bunun nedeni Anahtar Kelime Listelerinin yinelenen anahtarlara sahip olabilmesinden mi? Neden hem Harita stili erişim hem de yinelenen anahtarlar istiyorsunuz?

Verim? Bunun nedeni Anahtar Kelime Listelerinin daha iyi performans göstermesi mi? Öyleyse neden Haritalar var? Ve haritalar, üyeleri anahtara göre aramada tuple listesinden daha başarılı olmamalı mı?

JS Dizisi ve Ruby Hash gibi bir görünüm? Öyle mi?

Yapısal olarak farklı veri temsilleri olduklarını anlıyorum. Bana göre iksirdeki Anahtar Kelime Listeleri, istisnai sözdizimi (3 farklı sözdizimsel varyant), kullanım durumu haritalarla örtüşme ve belirsiz bir fayda yoluyla dili karmaşıklaştırmaya hizmet ediyor gibi görünüyor.

Anahtar Kelime Listelerini kullanmanın faydası nedir?

Yanıtlar:


143
                   ┌──────────────┬────────────┬───────────────────────┐
                   │ 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⁴                 │
└──────────────────┴──────────────┴────────────┴───────────────────────┘

Anahtar kelime listeleri hafiftir ve altlarında basit bir yapıya sahiptir, bu da onları çok esnek kılar. Bunları bir Erlang sözleşmesinin üstüne sözdizimi şekeri olarak düşünebilirsiniz, bu da çok çirkin kod yazmadan Erlang ile arayüz oluşturmayı kolaylaştırır. Örneğin, anahtar kelime listeleri, Erlang'dan miras alınan bir özellik olan işlev bağımsız değişkenlerini temsil etmek için kullanılır. Bazı durumlarda, özellikle yinelenen anahtarlara veya sıralamaya ihtiyacınız varsa, anahtar kelime listeleri tek seçeneğinizdir. Diğer alternatiflerden farklı özelliklere sahiptirler, bu da onları bazı durumlar için daha uygun ve diğerleri için daha az kılar.

Haritalar (ve Yapılar), karma tabanlı bir uygulamaya sahip olduklarından gerçek yük verilerini depolamak için kullanılır. Anahtar kelime listeleri dahili olarak her işlem için geçilmesi gereken listelerden ibarettir, bu nedenle sabit zamanlı erişim gibi klasik anahtar-değer veri yapılarının özelliklerine sahip değildirler.

Elixir , yazıldığı sırada haritaların düşük performansıHashDict için bir çözüm olarak tanıtıldı . Ancak bu durum Elixir 1.0.5 / Erlang 18.0'dan itibaren düzeltilmiştir ve gelecek sürümlerde kullanımdan kaldırılacaktır .HashDict

Erlang standart kitaplığında daha derine inerseniz, anahtar / değer çiftlerini depolayan daha da fazla veri yapısı vardır:

  • proplists - Elixir anahtar kelime listelerine benzer
  • haritalar - Elixir haritalarıyla aynı
  • dict - Erlang ilkellerinden oluşturulmuş anahtar-değer sözlükleri
  • gb_trees - genel dengeli ağaç

Anahtar / değer çiftlerini birden çok işlem ve / veya VM'de depolamanız gerektiğinde de şu seçeneklere sahip olursunuz:

  • ets / dets - (disk tabanlı) Erlang terimi depolama
  • mnesia - dağıtılmış veritabanı

¹ Genel olarak konuşursak, ama tabii ki değişir ™.

² En iyi durum, bir listenin başına eklemektir.

³ Elixir 1.0.5 ve üzeri için geçerlidir, eski sürümlerde daha yavaş olabilir.

HashDictartık kullanımdan kaldırılıyor.

⁵ Ortalama olarak öğelerin yarısını tarayan doğrusal bir arama gerektirir.


1
Yinelenen anahtarlara izin vermek ve sipariş edilmek faydalar değil, farklı özelliklerdir. İhtiyaçlarınıza uygun veri yapısını seçmeniz gerekir.
rightfold

2
Kesinlikle, evet, ancak bu özelliklere ihtiyacınız varsa faydalı olabilirler - bunu kastettim.
Patrick Oscity

@PatrickOscity: Böyle bir durumda, kesinlikle gereksinimler olarak daha iyi sınıflandırılırlar mı?
Orbit'te Hafiflik Yarışları

11
@greggreg Anahtar kelime listelerine sahip olmanın başka bir örtük yararı daha vardır: yapılandırılmış ve yapılandırılmamış veriler hakkında bir ayrım yaparız. Haritalar, bilinen bir anahtar kümesine sahip yapılandırılmış veriler için son derece yararlıdır ve anahtar sözcükler değildir. Bugün, harita kullanımının çoğu yapılandırılmış veriler içindir ve isteğe bağlı olanlar için anahtar kelimeler bırakıyoruz. Sadece haritalarımız olsaydı, bu ayrımın büyük bir kısmının kaybolacağını düşünüyorum.
José Valim

1
Aslında öyleydi, haritalar erlang 18'den gitmenin yolu.
Papipo

12

Anahtar kelime listelerinin ana yararı, mevcut iksir ve erlang kod tabanıyla geriye dönük uyumluluktur.

Ruby sözdizimine benzeyen işlev bağımsız değişkenleri olarak kullanılırsa sözdizimi şekeri de eklerler:

def some_fun(arg, opts \\ []), do: ...
some_fun arg, opt1: 1, opt2: 2

Anahtar kelime listelerini kullanmanın ana dezavantajı, bunlar üzerinde kısmi bir kalıp eşleştirmesi gerçekleştirmenin mümkün olmamasıdır:

iex(1)> m = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(2)> %{a: a} = m
%{a: 1, b: 2}
iex(3)> a
1
iex(4)> k = [a: 1, b: 2]
[a: 1, b: 2]
iex(5)> [a: a] = k
** (MatchError) no match of right hand side value: [a: 1, b: 2]

Bunu işlev argümanlarına genişletelim. Seçeneklerden birinin değerine bağlı olarak çok kullanımlı bir işlevi ele almamız gerektiğini düşünün:

def fun1(arg, opt1: opt1) when is_nil(opt1), do: do_special_thing
def fun1(arg, opts), do: do_regular_thing

def fun2(arg, %{opt1: opt1}) when is_nil(opt1), do: do_special_thing
def fun2(arg, opts), do: do_regular_thing

Bu asla aşağıdakileri yürütmez do_special_thing:

fun1("arg", opt1: nil, opt2: "some value")
doing regular thing  

Harita argümanlarıyla şu şekilde çalışacaktır:

fun2("arg", %{opt1: nil, opt2: "some value"})
doing special thing

2

Haritalar, belirli bir anahtar için yalnızca bir girişe izin verirken, anahtar kelime listeleri anahtarın tekrarlanmasına izin verir. Haritalar etkilidir (özellikle büyüdükçe) ve Elixir'in desen eşleştirmesinde kullanılabilirler.

Genel olarak, komut satırı parametreleri gibi şeyler ve seçenekler arasında geçiş yapmak için anahtar sözcük listelerini kullanın ve ilişkilendirilebilir bir dizi istediğinizde haritaları (veya başka bir veri yapısı olan HashDict) kullanın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.