ดีถ้าคุณดูลึกลงไปทั้งสองรวมถึงอาร์เรย์ในภาษาพื้นฐานเช่นกัน:
- รายงาน Scheme ที่แก้ไขครั้งที่ 5 (R5RS) รวมถึงประเภทเวกเตอร์ซึ่งเป็นคอลเลกชันที่เป็นดัชนีจำนวนเต็มขนาดคงที่ซึ่งดีกว่าเวลาเชิงเส้นสำหรับการเข้าถึงแบบสุ่ม
- รายงาน Haskell 98 มีประเภทอาร์เรย์เช่นกัน
อย่างไรก็ตามการเรียนการสอนการเขียนโปรแกรมการทำงานมีความยาวเน้นรายการเชื่อมโยงเดียวมากกว่าอาร์เรย์หรือรายการที่เชื่อมโยงสองครั้ง มีแนวโน้มที่จะเน้นมากเกินไปในความเป็นจริง อย่างไรก็ตามมีสาเหตุหลายประการ
รายการแรกคือรายการที่เชื่อมโยงเดี่ยวเป็นหนึ่งในประเภทข้อมูลแบบเรียกซ้ำที่ง่ายที่สุดและมีประโยชน์ที่สุด ผู้ใช้กำหนดประเภทรายการของ Haskell สามารถกำหนดดังนี้:
data List a -- A list with element type `a`...
= Empty -- is either the empty list...
| Cell a (List a) -- or a pair with an `a` and the rest of the list.
ความจริงที่ว่ารายการเป็น recursive ชนิดข้อมูลหมายความว่าฟังก์ชั่นการทำงานที่อยู่ในรายชื่อโดยทั่วไปใช้เรียกซ้ำโครงสร้าง ในเงื่อนไข Haskell: คุณจับคู่รูปแบบกับตัวสร้างรายการและคุณแบ่งส่วนย่อยของรายการ ในนิยามฟังก์ชันพื้นฐานทั้งสองนี้ฉันใช้ตัวแปรas
เพื่ออ้างถึงส่วนท้ายของรายการ ดังนั้นโปรดทราบว่าการเรียกซ้ำเรียกว่า "ลง" รายการ:
map :: (a -> b) -> List a -> List b
map f Empty = Empty
map f (Cell a as) = Cell (f a) (map f as)
filter :: (a -> Bool) -> List a -> List a
filter p Empty = Empty
filter p (Cell a as)
| p a = Cell a (filter p as)
| otherwise = filter p as
เทคนิคนี้รับประกันว่าฟังก์ชั่นของคุณจะยุติสำหรับรายการที่ จำกัด ทั้งหมดและยังเป็นเทคนิคการแก้ปัญหาที่ดี - มันมีแนวโน้มที่จะแยกปัญหาออกเป็นส่วนย่อยที่ง่ายกว่า
ดังนั้นรายการแบบลิงก์เดียวอาจเป็นชนิดข้อมูลที่ดีที่สุดในการแนะนำนักเรียนถึงเทคนิคเหล่านี้ซึ่งมีความสำคัญมากในการเขียนโปรแกรมเชิงฟังก์ชัน
เหตุผลที่สองคือน้อยของ "เหตุผลที่รายการเดียวที่เชื่อมโยง" เหตุผล แต่มากขึ้นของ "ทำไมไม่รายการสองครั้งที่เชื่อมโยงหรืออาร์เรย์" เหตุผล: ผู้ชนิดข้อมูลหลังมักจะเรียกร้องให้เกิดการกลายพันธุ์ (ตัวแปรที่สามารถปรับเปลี่ยนได้) ซึ่งโปรแกรมการทำงานบ่อยมาก ห่างจาก ดังนั้นเมื่อมันเกิดขึ้น:
- ในภาษาที่กระตือรือร้นเช่น Scheme คุณไม่สามารถสร้างรายการที่เชื่อมโยงสองครั้งได้โดยไม่ต้องใช้การกลายพันธุ์
- ในภาษาขี้เกียจเช่น Haskell คุณสามารถสร้างรายการที่เชื่อมโยงสองครั้งโดยไม่ต้องใช้การกลายพันธุ์ แต่เมื่อใดก็ตามที่คุณสร้างรายการใหม่ตามรายการนั้นคุณจะถูกบังคับให้คัดลอกส่วนใหญ่หากไม่ใช่โครงสร้างทั้งหมดของต้นฉบับ ในขณะที่มีรายการเชื่อมโยงเดี่ยวคุณสามารถเขียนฟังก์ชั่นที่ใช้ "การแบ่งปันโครงสร้าง" - รายการใหม่สามารถนำเซลล์ของรายการเก่ากลับมาใช้ใหม่ได้ตามความเหมาะสม
- ตามเนื้อผ้าถ้าคุณใช้อาร์เรย์ในลักษณะที่ไม่เปลี่ยนรูปก็หมายความว่าทุกครั้งที่คุณต้องการปรับเปลี่ยนอาร์เรย์ที่คุณต้องคัดลอกทุกสิ่ง (ไลบรารี Haskell ล่าสุดเช่น
vector
อย่างไรก็ตามพบเทคนิคที่ปรับปรุงอย่างมากในปัญหานี้)
เหตุผลที่สามและครั้งสุดท้ายนำไปใช้กับภาษาที่ขี้เกียจเช่น Haskell เป็นหลัก: รายการที่เชื่อมโยงเดี่ยวแบบขี้เกียจในทางปฏิบัติมักจะคล้ายกับตัววนซ้ำมากกว่ารายการในหน่วยความจำที่เหมาะสม หากรหัสของคุณใช้องค์ประกอบของรายการตามลำดับและโยนทิ้งในขณะที่คุณไปรหัสวัตถุจะทำให้เซลล์รายการและเนื้อหาในรายการเป็นจริงในขณะที่คุณก้าวไปข้างหน้าผ่านรายการ
ซึ่งหมายความว่ารายการทั้งหมดไม่จำเป็นต้องมีอยู่ในหน่วยความจำพร้อมกันเฉพาะเซลล์ปัจจุบัน เซลล์ก่อนที่ปัจจุบันจะเป็นที่เก็บขยะ (ซึ่งจะไม่สามารถทำได้ด้วยรายการที่เชื่อมโยงสองครั้ง); เซลล์ช้ากว่าเซลล์ปัจจุบันไม่จำเป็นต้องคำนวณจนกว่าคุณจะไปถึงที่นั่น
มันยิ่งไปกว่านั้น มีเทคนิคที่ใช้ในห้องสมุด Haskell ยอดนิยมหลายแห่งที่เรียกว่าฟิวชั่นโดยที่คอมไพเลอร์วิเคราะห์รหัสการประมวลผลรายการของคุณและรายการจุดตรงกลางที่ถูกสร้างและบริโภคตามลำดับแล้ว "ทิ้ง ด้วยความรู้นี้คอมไพเลอร์สามารถกำจัดการจัดสรรหน่วยความจำของเซลล์รายการเหล่านั้นได้อย่างสมบูรณ์ ซึ่งหมายความว่ารายการเดียวที่เชื่อมโยงในโปรแกรมต้นฉบับ Haskell หลังจากการรวบรวมอาจจะกลายเป็นวนซ้ำแทนที่จะเป็นโครงสร้างข้อมูล
ฟิวชั่นยังเป็นเทคนิคที่vector
ห้องสมุดดังกล่าวใช้ในการสร้างรหัสที่มีประสิทธิภาพสำหรับอาร์เรย์ที่ไม่เปลี่ยนรูป เช่นเดียวกันสำหรับไลบรารีbytestring
(ไบต์อาร์เรย์) และtext
(สตริง Unicode) ที่ได้รับความนิยมอย่างมากซึ่งถูกสร้างขึ้นเพื่อแทนที่ประเภทเนทีฟที่ไม่ได้ยอดเยี่ยมมากของ Haskell String
(ซึ่งเหมือนกับ[Char]
รายการอักขระเดียวที่เชื่อมโยง) ดังนั้นใน Haskell สมัยใหม่จึงมีแนวโน้มที่ประเภทอาเรย์ที่ไม่เปลี่ยนรูปพร้อมการรองรับฟิวชั่นจะกลายเป็นเรื่องธรรมดา
รายการฟิวชั่นอำนวยความสะดวกโดยข้อเท็จจริงที่ว่าในรายการเดียวที่เชื่อมโยงคุณสามารถไปข้างหน้าแต่ไม่เคยย้อนกลับ สิ่งนี้นำเสนอชุดรูปแบบที่สำคัญมากในการเขียนโปรแกรมฟังก์ชั่น: การใช้ "รูปร่าง" ของชนิดข้อมูลเพื่อให้ได้ "รูปร่าง" ของการคำนวณ หากคุณต้องการประมวลผลองค์ประกอบตามลำดับรายการเดียวที่เชื่อมโยงคือชนิดข้อมูลที่เมื่อคุณใช้มันด้วยการเรียกซ้ำโครงสร้างจะให้รูปแบบการเข้าถึงนั้นเป็นธรรมชาติ หากคุณต้องการใช้กลยุทธ์ "แบ่งและพิชิต" เพื่อโจมตีปัญหาโครงสร้างข้อมูลแบบต้นไม้มักจะให้การสนับสนุนได้เป็นอย่างดี
ผู้คนจำนวนมากเลื่อนออกจากเกวียนการเขียนโปรแกรมการทำงานก่อนเพื่อให้พวกเขาได้สัมผัสกับรายการที่เชื่อมโยงเดียว แต่ไม่ให้ความคิดพื้นฐานที่สูงขึ้น