ใน Clojure ฉันควรใช้เวกเตอร์กับรายการและวิธีอื่น ๆ เมื่อใด


147

ฉันอ่านแล้วว่า Vectors ไม่ใช่ seqs แต่ Lists คือ ฉันไม่แน่ใจว่าเหตุผลสำหรับการใช้อย่างใดอย่างหนึ่งมากกว่าที่อื่น ดูเหมือนว่าเวกเตอร์จะถูกใช้มากที่สุด แต่มีเหตุผลสำหรับสิ่งนั้นหรือไม่?


คำตอบ:


112

ดูเหมือนว่าฉันจะตอบคำถามของฉันเองด้วยการใจร้อนและถามใน #clojure บน Freenode สิ่งที่ดีในการตอบคำถามของคุณได้รับการสนับสนุนบน Stackoverflow.com: D

ฉันได้พูดคุยอย่างรวดเร็วกับ Rich Hickey และนี่คือส่วนสำคัญของมัน

[12:21] <Raynes>    Vectors aren't seqs, right?
[12:21] <rhickey>   Raynes: no, but they are sequential
[12:21] <rhickey>   ,(sequential? [1 2 3])
[12:21] <clojurebot>    true
[12:22] <Raynes>    When would you want to use a list over a vector?
[12:22] <rhickey>   when generating code, when generating back-to-front
[12:23] <rhickey>   not too often in Clojure

ขณะที่คุณอยู่ในโหมด freenode มาที่ด้านมืดและเข้าร่วม #stackoverflow! :-P
Chris Jester-Young

จริง ๆ แล้วฉันเคยว่างที่นั่น ฉันเปลี่ยนลูกค้า IRC และไม่เคยคิดที่จะเพิ่ม #stackoverflow ในรายการ autojoin ของฉัน
Rayne

ฉันเป็นมือใหม่เสียงกระเพื่อม แต่ฉันสงสัยว่าเวกเตอร์แผนที่และชุดแตกในบางวิธีที่ความคิดที่ว่ารหัสทั้งหมดสามารถใช้แทนกันกับข้อมูลได้หรือไม่? หรือนี่เป็นเพียงหนึ่งในสิ่งเหล่านั้นที่ทำให้ Clojure ใช้เสียงกระเพื่อม (หรือคุณสามารถประเมินเวกเตอร์ได้หรือไม่)
Rob Grant

23
นี่เป็นตัวอย่างแชทที่ไม่ช่วยเหลืออย่างสมบูรณ์ "Generating code" "กำลังสร้าง back-to-front" -> แปลว่าอะไร ฉันมีปัญหากับคำถามนี้จริงๆเพราะในหนังสือของฉันขี้เกียจ + สไตล์การประกาศ = มีประสิทธิภาพที่ดีกว่าและยังมีเวกเตอร์แนะนำทุกที่ใน Clojure ซึ่งทำให้ฉันสับสนโดยสิ้นเชิง
จิมมี่ฮอฟฟา

22
@JimmyHoffa วิธีที่ฉันเข้าใจ: "Generating Code" = "Inside a Macro" (เพราะส่วนใหญ่ของรหัสคือการเรียกใช้ฟังก์ชั่นจึงแสดงรายการ); "กำลังสร้างกลับไปข้างหน้า" = "การสร้างลำดับโดยการเติม"
omiel

87

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

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

โดยวิธีการที่เวกเตอร์สามารถกลายเป็น seqs ได้อย่างง่ายดาย

user=> (def v (vector 1 2 3))
#'user/v
user=> v
[1 2 3]
user=> (seq v)
(1 2 3)
user=> (rseq v)
(3 2 1)

เวกเตอร์ไม่ใช่ seqs แต่เป็นลำดับ (ที่มา: ทำให้รวยใน #clojure บน freenode) นอกจากนี้ฉันไม่รู้ Java เลย แต่ Rich ก็ตอบคำถามของฉัน
Rayne

1
ฉันจะแก้ไขโพสต์ของฉันเพื่อบอกว่า, เวกเตอร์สามารถทำเป็น seqs, ผ่านฟังก์ชัน seq :-)
Chris Jester-Young

2
เลือกคำตอบของคุณเพราะจริง ๆ แล้วตอบคำถามและฉันไม่ชอบเลือกคำตอบของฉันเองอย่างถูกต้อง ดูไม่ถูกต้อง ขอบคุณ :)
Rayne

deque ดีกว่ารายการที่เชื่อมโยงในกรณีของการเพิ่มก่อนและสุดท้าย LLs นั้นแย่มาก: P
บรรจุกล่อง

1
@boxed คุณไม่สามารถใช้ deque บนเวกเตอร์หรือArrayListไม่ใช้อย่างมีประสิทธิภาพนำมาใช้ใหม่ArrayDequeด้วยตนเอง
Chris Jester-Young

43

เวกเตอร์มีเวลาเข้าถึงแบบสุ่ม O (1) แต่จะต้องมีการจัดสรรล่วงหน้า รายการสามารถขยายได้แบบไดนามิก แต่การเข้าถึงองค์ประกอบแบบสุ่มคือ O (n)


3
ในทางเทคนิครายการที่ลิงก์จะมีเวลาเข้าถึง O (1) ... หากคุณเข้าถึงองค์ประกอบด้านหน้าหรือด้านหลังเท่านั้น :-P อย่างไรก็ตามเวกเตอร์มีการเข้าถึงแบบสุ่ม O (1) :-)
Chris Jester-Young

4
("รายการที่เชื่อมโยง" ตามที่อธิบายไว้ข้างต้นอ้างถึงรายการที่เชื่อมโยงเป็นสองเท่ารายการที่เชื่อมโยงเดี่ยว ๆ มีการเข้าถึง O (1) ไปที่องค์ประกอบด้านหน้าเท่านั้น :-P)
Chris Jester-Young

1
ในฐานะที่เป็นคนที่เพิ่งดำดิ่งสู่ Clojure นี่เป็นคำตอบที่ดีกว่าอีกสองคำตอบที่มีคะแนนมากกว่า อีกสองคนบอกว่าไม่มีประโยชน์อะไร
keithjgrant

รายการ @ ChrisJester หนุ่มโสดที่เชื่อมโยงสามารถรองรับ O (1) การเข้าถึงด้านหลังถ้าจะเก็บการอ้างอิงถึงองค์ประกอบด้านหลังเช่นเดียวกับที่
Gates Bates

30

เมื่อใดควรใช้เวกเตอร์:

  • ประสิทธิภาพการเข้าถึงที่จัดทำดัชนี - คุณจะได้รับค่าใช้จ่าย ~ O (1) สำหรับการเข้าถึงที่ทำดัชนีกับ O (n) สำหรับรายการ
  • ผนวก - ด้วย conj คือ ~ O (1)
  • สัญกรณ์สะดวก - ฉันคิดว่ามันง่ายกว่าในการพิมพ์และอ่าน [1 2 3] มากกว่า '(1 2 3) สำหรับรายการตัวอักษรในสถานการณ์ที่ทั้งสองจะทำงาน

เมื่อใดที่จะใช้รายการ:

  • เมื่อคุณต้องการเข้าถึงมันเป็นลำดับ (เนื่องจากรายการสนับสนุนโดยตรง seq โดยไม่ต้องจัดสรรวัตถุใหม่)
  • กำลังเตรียม - การเพิ่มไปยังจุดเริ่มต้นของรายการที่มีข้อเสียหรือควรรวมเป็น O (1)

3
แม้ว่าการเพิ่ม / ลบที่ปลายทั้งสองรายการจะเป็นตัวเลือกที่น่ากลัว deque ดีกว่ามาก (ใน CPU และหน่วยความจำโดยเฉพาะ) ลองgithub.com/pjstadig/deque-clojure
ชนิดบรรจุกล่อง

2
Re: ~O(1)สำหรับผู้ที่คำอธิบายค่าใช้จ่ายนี้อาจเป็นประโยชน์ - stackoverflow.com/questions/200384/constant-amortized-time
Merlyn Morgan-Graham

13

เพียงแค่ทราบอย่างรวดเร็ว:

"ฉันอ่านแล้วเวกเตอร์ไม่ใช่คำถาม แต่เป็นรายการ" 

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

user> (class (list 1 2 3))
clojure.lang.PersistentList

user> (class (seq (list 1 2 3)))
clojure.lang.PersistentList

user> (class (seq [1 2 3]))
clojure.lang.PersistentVector$ChunkedSeq

Sec มีช็อตคัตที่คืนค่าอาร์กิวเมนต์ถ้ามันเป็น seq อยู่แล้ว:

user> (let [alist (list 1 2 3)] (identical? alist (seq alist)))
true
user> (identical? (list 1 2 3) (seq (list 1 2 3)))
false

static public ISeq seq(Object coll){
        if(coll instanceof ASeq)
                return (ASeq) coll;
        else if(coll instanceof LazySeq)
                return ((LazySeq) coll).seq();
        else
                return seqFrom(coll);
}

รายการเป็นลำดับแม้ว่าสิ่งอื่น ๆ เช่นกันและไม่ใช่ลำดับทั้งหมดเป็นรายการ


ฉันไม่ได้หมายถึงการเลือกจุดเล็ก ๆ มันเป็นโอกาสที่จะชี้ให้เห็นสิ่งที่มีประโยชน์ จำนวนมากอยู่แล้วจะได้รู้ว่านี้ :)
อาร์เธอร์ Ulfeldt

2
คุณไม่ได้หมายถึงclassแทนที่จะเป็นclass?เหรอ?
qerub

ไม่แน่ใจว่าตัวอย่างของคุณมีการเปลี่ยนแปลงตามการปรับปรุง clojure (ฉันคิดว่าฉันใน 1.5) แต่ทั้งสองตัวอย่างของคุณกลับมาclojure.lang.PersistentListให้ฉัน ฉันสมมติว่าคุณหมายถึงการเขียนไม่ได้class class?
Adrian Mouat

ฉันทำอย่างแน่นอน! ฉันจะแก้ไข
Arthur Ulfeldt

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