ประโยชน์ของรายการคำหลักคืออะไร?


101

ในยาอายุวัฒนะเรามีแผนที่:

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

ทำไมทั้งสอง?

ไวยากรณ์? เป็นเพราะรายการคำหลักมีไวยากรณ์ที่ยืดหยุ่นกว่าทำให้สามารถกำหนดได้โดยไม่ต้องหยิกและไม่มีวงเล็บเป็นพารามิเตอร์สุดท้ายของการเรียกฟังก์ชันหรือไม่ ถ้าอย่างนั้นทำไมไม่ให้น้ำตาลเชิงไวยากรณ์นี้แก่ Maps?

คีย์ที่ซ้ำกัน? เป็นเพราะรายการคำหลักสามารถมีคีย์ที่ซ้ำกันได้หรือไม่? ทำไมคุณถึงต้องการทั้งการเข้าถึงรูปแบบแผนที่และคีย์ที่ซ้ำกัน

ประสิทธิภาพ? เป็นเพราะรายการคำหลักมีประสิทธิภาพที่ดีกว่าหรือไม่? แล้วทำไมต้องมี Maps? และแผนที่ไม่ควรมีประสิทธิภาพในการค้นหาสมาชิกด้วยคีย์มากกว่ารายการทูเปิลหรือไม่?

JS Array และ Ruby Hash มีลักษณะอย่างไร มันคืออะไร?

ฉันเข้าใจว่าโครงสร้างเป็นการแสดงข้อมูลที่แตกต่างกัน สำหรับฉันแล้วดูเหมือนว่ารายการคำหลักในน้ำอมฤตทำหน้าที่ทำให้ภาษาซับซ้อนผ่านไวยากรณ์ที่โดดเด่น (รูปแบบทางไวยากรณ์ที่แตกต่างกัน 3 แบบ) ใช้กรณีที่ทับซ้อนกับแผนที่และประโยชน์ที่ไม่ชัดเจน

ประโยชน์ของการใช้รายการคำหลักคืออะไร?

คำตอบ:


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⁴                 │
└──────────────────┴──────────────┴────────────┴───────────────────────┘

รายการคำหลักมีน้ำหนักเบาและมีโครงสร้างที่เรียบง่ายอยู่ข้างใต้ซึ่งทำให้มีความยืดหยุ่นมาก คุณสามารถคิดว่าพวกเขาเป็นน้ำตาลไวยากรณ์ที่อยู่ด้านบนของหลักการ Erlang ทำให้ง่ายต่อการเชื่อมต่อกับ Erlang โดยไม่ต้องเขียนโค้ดที่น่าเกลียดเกินไป ตัวอย่างเช่นรายการคำหลักถูกใช้เพื่อแสดงอาร์กิวเมนต์ของฟังก์ชันซึ่งเป็นคุณสมบัติที่สืบทอดมาจาก Erlang ในบางกรณีรายการคำหลักเป็นทางเลือกเดียวของคุณโดยเฉพาะอย่างยิ่งหากคุณต้องการคีย์ซ้ำหรือลำดับ เพียงแค่มีคุณสมบัติที่แตกต่างจากทางเลือกอื่น ๆ ซึ่งทำให้เหมาะกับบางสถานการณ์และน้อยกว่าสำหรับคนอื่น ๆ

แผนที่ (และโครงสร้าง) ใช้ในการจัดเก็บข้อมูลเพย์โหลดจริงเนื่องจากมีการใช้งานตามแฮช รายการคำหลักภายในเป็นเพียงรายการที่ต้องข้ามผ่านสำหรับแต่ละการดำเนินการดังนั้นจึงไม่มีคุณสมบัติของโครงสร้างข้อมูลคีย์ - ค่าแบบคลาสสิกเช่นการเข้าถึงเวลาคงที่

Elixir ยังแนะนำHashDictเป็นวิธีแก้ปัญหาสำหรับที่ประสิทธิภาพที่ดีของแผนที่ในเวลาที่มันถูกเขียนขึ้น อย่างไรก็ตามตอนนี้ได้รับการแก้ไขแล้วตั้งแต่ Elixir 1.0.5 / Erlang 18.0 และHashDict จะเลิกใช้งานในเวอร์ชันต่อ ๆไป

หากคุณเจาะลึกลงไปในไลบรารีมาตรฐาน Erlang จะมีโครงสร้างข้อมูลเพิ่มเติมที่เก็บคู่คีย์ / ค่า:

  • proplists - คล้ายกับรายการคีย์เวิร์ด Elixir
  • แผนที่ - เหมือนกับแผนที่ Elixir
  • dict - พจนานุกรมคีย์ - ค่าที่สร้างขึ้นจากดั้งเดิมของ Erlang
  • gb_trees - ต้นไม้สมดุลทั่วไป

คุณยังมีตัวเลือกเหล่านี้เมื่อคุณต้องการจัดเก็บคู่คีย์ / ค่าในกระบวนการต่างๆและ / หรือ VMs:

  • ets / dets - (ตามดิสก์) การจัดเก็บระยะ Erlang
  • mnesia - ฐานข้อมูลแบบกระจาย

¹พูดโดยทั่วไป แต่แน่นอนขึ้นอยู่กับ

²กรณีที่ดีที่สุดเป็นเพียงการนำเสนอรายการ

³ใช้กับ Elixir 1.0.5 ขึ้นไปอาจช้ากว่าในเวอร์ชันเก่า

HashDictกำลังเลิกใช้งาน

⁵ต้องใช้การค้นหาเชิงเส้นซึ่งโดยเฉลี่ยแล้วจะสแกนองค์ประกอบครึ่งหนึ่ง


1
การอนุญาตให้คีย์ซ้ำกันและการเรียงลำดับไม่เป็นประโยชน์ แต่คุณสมบัติที่แตกต่างกัน คุณต้องเลือกโครงสร้างข้อมูลที่เหมาะกับความต้องการของคุณ
พับขวา

2
พูดอย่างเคร่งครัดใช่ แต่อาจกลายเป็นประโยชน์หากคุณต้องการคุณสมบัติเหล่านั้นนั่นคือสิ่งที่ฉันหมายถึง
Patrick Oscity

@PatrickOscity: ในกรณีนี้แน่นอนว่าพวกเขาจะถูกจัดหมวดหมู่ตามความต้องการได้ดีขึ้น?
Lightness Races ในวงโคจร

11
@greggreg มีประโยชน์โดยปริยายอีกประการหนึ่งของการมีรายการคำหลัก: เราสร้างความแตกต่างเกี่ยวกับข้อมูลที่มีโครงสร้างและไม่มีโครงสร้าง แผนที่มีประโยชน์อย่างยิ่งสำหรับข้อมูลที่มีโครงสร้างซึ่งไม่มีชุดคีย์และคำหลักที่รู้จัก ปัจจุบันการใช้แผนที่ส่วนใหญ่เป็นข้อมูลที่มีโครงสร้างและเราปล่อยให้คำหลักเป็นตัวเลือก หากเรามีเพียงแผนที่ฉันคิดว่าส่วนที่ดีของความแตกต่างนี้จะหายไป
José Valim

1
ในความเป็นจริงแผนที่เป็นวิธีที่จะไปจาก erlang 18.
Papipo

12

ประโยชน์หลักของรายการคำหลักคือความเข้ากันได้แบบย้อนหลังกับ elixir และ erlang codebase ที่มีอยู่

นอกจากนี้ยังเพิ่มน้ำตาลไวยากรณ์หากใช้เป็นอาร์กิวเมนต์ของฟังก์ชันที่คล้ายกับไวยากรณ์ของทับทิม:

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

ข้อเสียเปรียบหลักของการใช้รายการคำหลักคือไม่สามารถทำการจับคู่รูปแบบบางส่วนได้:

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]

ลองขยายเป็นอาร์กิวเมนต์ของฟังก์ชัน ลองนึกภาพว่าเราจำเป็นต้องจัดการฟังก์ชันมัลติคลอสตามค่าของตัวเลือกใดตัวเลือกหนึ่ง:

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

สิ่งนี้จะไม่ดำเนินการdo_special_thing:

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

ด้วยข้อโต้แย้งของแผนที่จะใช้งานได้:

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

2

Maps อนุญาตให้ป้อนคีย์หนึ่งรายการเท่านั้นในขณะที่รายการคีย์เวิร์ดอนุญาตให้คีย์ซ้ำ แผนที่มีประสิทธิภาพ (โดยเฉพาะอย่างยิ่งเมื่อเติบโตขึ้น) และสามารถใช้ในการจับคู่รูปแบบของ Elixir

โดยทั่วไปใช้รายการคำสำคัญสำหรับสิ่งต่างๆเช่นพารามิเตอร์บรรทัดคำสั่งและสำหรับการส่งผ่านตัวเลือกต่างๆและใช้แผนที่ (หรือโครงสร้างข้อมูลอื่น HashDict) เมื่อคุณต้องการอาร์เรย์ที่เชื่อมโยง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.