เหตุใด Haskell และ Scheme จึงใช้รายการที่เชื่อมโยงโดยลำพัง


12

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


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

3
ลองคิดดูสิคุณจะสร้างรายการที่ไม่เปลี่ยนรูปแบบที่เชื่อมโยงซ้ำได้อย่างไร คุณต้องมีnextตัวชี้ขององค์ประกอบก่อนหน้าชี้ไปที่องค์ประกอบถัดไปและprevตัวชี้ขององค์ประกอบถัดไปชี้ไปที่องค์ประกอบก่อนหน้า อย่างไรก็ตามหนึ่งในสององค์ประกอบนั้นถูกสร้างขึ้นก่อนหน้าซึ่งหมายความว่าหนึ่งในองค์ประกอบเหล่านั้นจำเป็นต้องมีตัวชี้ที่ชี้ไปยังวัตถุที่ยังไม่มีอยู่! จำไว้ว่าคุณไม่สามารถสร้างองค์ประกอบหนึ่งก่อนจากนั้นองค์ประกอบอื่นแล้วตั้งค่าพอยน์เตอร์ - มันไม่เปลี่ยนรูป (หมายเหตุ: ฉันรู้ว่ามีวิธีหาประโยชน์จากความเกียจคร้านเรียกว่า "Tying the Knot")
Jörg W Mittag

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

คำตอบ:


23

ดีถ้าคุณดูลึกลงไปทั้งสองรวมถึงอาร์เรย์ในภาษาพื้นฐานเช่นกัน:

  • รายงาน 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 สมัยใหม่จึงมีแนวโน้มที่ประเภทอาเรย์ที่ไม่เปลี่ยนรูปพร้อมการรองรับฟิวชั่นจะกลายเป็นเรื่องธรรมดา

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

ผู้คนจำนวนมากเลื่อนออกจากเกวียนการเขียนโปรแกรมการทำงานก่อนเพื่อให้พวกเขาได้สัมผัสกับรายการที่เชื่อมโยงเดียว แต่ไม่ให้ความคิดพื้นฐานที่สูงขึ้น


1
ช่างเป็นคำตอบที่ยอดเยี่ยม!
Elliot Gorokhovsky

14

เพราะมันใช้งานได้ดีกับการเปลี่ยนไม่ได้ สมมติว่าคุณมีสองรายการไม่เปลี่ยนรูปและ[1, 2, 3] [10, 2, 3]แสดงให้เห็นว่าเป็นรายการเชื่อมโยงเดี่ยว ๆ ที่แต่ละรายการในรายการเป็นโหนดที่มีรายการและตัวชี้ไปยังส่วนที่เหลือของรายการพวกเขาจะมีลักษณะเช่นนี้:

node -> node -> node -> empty
 1       2       3

node -> node -> node -> empty
 10       2       3

ดูว่า[2, 3]ส่วนต่าง ๆ เหมือนกันอย่างไร ด้วยโครงสร้างข้อมูลที่ไม่แน่นอนพวกเขาทั้งสองรายการต่างกันเพราะรหัสที่เขียนข้อมูลใหม่ไปยังหนึ่งในนั้นต้องไม่ส่งผลกระทบต่อรหัสโดยใช้อีกอันหนึ่ง ด้วยการเปลี่ยนรูปข้อมูล แต่เรารู้ว่าเนื้อหาของรายการจะไม่เปลี่ยนแปลงและรหัสไม่สามารถเขียนข้อมูลใหม่ ดังนั้นเราสามารถใช้ก้อยได้อีกครั้งและให้ทั้งสองลิสต์มีส่วนร่วมในโครงสร้าง:

node -> node -> node -> empty
 1      ^ 2       3
        |
node ---+
 10

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

อย่างไรก็ตามหากคุณลองและแสดง[1, 2, 3]และเชื่อมโยง[10, 2, 3]เป็นสองเท่ารายการ:

node <-> node <-> node <-> empty
 1       2       3

node <-> node <-> node <-> empty
 10       2       3

ตอนนี้ก้อยไม่เหมือนกันอีกต่อไป เป็นครั้งแรกที่[2, 3]มีตัวชี้ไป1ที่หัว 10แต่ที่สองมีตัวชี้ไปยัง นอกจากนี้หากคุณต้องการเพิ่มรายการใหม่ลงในส่วนหัวของรายการคุณต้องกลายพันธุ์ส่วนหัวก่อนหน้าของรายการเพื่อให้ชี้ไปที่ส่วนหัวใหม่

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


8
แม้ว่าการแบ่งปันแบบหางจะไม่เกิดขึ้นอย่างที่คุณบอก โดยทั่วไปไม่มีใครผ่านรายการทั้งหมดในหน่วยความจำและมองหาโอกาสในการรวมคำต่อท้ายทั่วไป การแบ่งปันเกิดขึ้นมันไม่ได้มาจากการเขียนอัลกอริธึมเช่นถ้าฟังก์ชั่นที่มีพารามิเตอร์xsสร้างขึ้น1:xsในที่เดียวและ10:xsอีกที่หนึ่ง

0

คำตอบ @ sacundim นั้นส่วนใหญ่เป็นเรื่องจริง แต่ก็มีข้อมูลเชิงลึกที่สำคัญอื่น ๆ เกี่ยวกับการแลกเปลี่ยนเกี่ยวกับการออกแบบภาษาและข้อกำหนดในทางปฏิบัติ

วัตถุและการอ้างอิง

ภาษาเหล่านี้มักจะมอบอำนาจ (หรือสมมติ) วัตถุที่มีขอบเขตแบบไดนามิกไม่ จำกัด(หรือในสำนวนของ C ตลอดชีวิตแม้ว่าจะไม่เหมือนกันเนื่องจากความแตกต่างของความหมายของวัตถุในภาษาเหล่านี้ดูด้านล่าง) โดยค่าเริ่มต้น เช่นตัวชี้วัตถุใน C) และพฤติกรรมที่ไม่สามารถคาดเดาได้ในกฎความหมาย (เช่นพฤติกรรมที่ไม่ได้กำหนดของ ISO C ที่เกี่ยวข้องกับความหมาย)

นอกจากนี้ความคิดของวัตถุ (ชั้นหนึ่ง) ในภาษาดังกล่าวมีข้อ จำกัด อย่างระมัดระวัง: ไม่มีการระบุคุณสมบัติ "ตำแหน่ง" และรับประกันตามค่าเริ่มต้น สิ่งนี้แตกต่างอย่างสิ้นเชิงในบางภาษาที่คล้ายกับ ALGOL ซึ่งวัตถุนั้นไม่มีส่วนขยายแบบไดนามิก (เช่นใน C และ C ++) ซึ่งโดยทั่วไปวัตถุหมายถึงบางส่วนของ

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

ปัญหาการจำลองโครงสร้างข้อมูล

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

แต่มีความแตกต่างอยู่เวกเตอร์ / ประเภทอาเรย์กับรายการที่เชื่อมโยงสองเท่า อาเรย์มักจะถูกสันนิษฐานว่ามีความซับซ้อนของเวลาในการเข้าถึง O (1) และค่าใช้จ่ายในพื้นที่น้อยซึ่งเป็นคุณสมบัติที่ยอดเยี่ยมที่ไม่ได้แชร์โดยรายการ (แม้ว่าจะพูดอย่างเคร่งครัดไม่รับประกันโดย ISO C แต่ผู้ใช้เกือบทุกคนคาดหวังและไม่มีการนำไปปฏิบัติจริงจะละเมิดการรับประกันโดยนัยเหล่านี้อย่างชัดเจน) OTOH รายการที่เชื่อมโยงเป็นสองเท่ามักทำให้คุณสมบัติทั้งสองแย่กว่ารายการที่เชื่อมโยงโดยลำพัง ในขณะที่การทำซ้ำย้อนหลัง / ไปข้างหน้าได้รับการสนับสนุนโดยอาร์เรย์หรือเวกเตอร์ (พร้อมกับดัชนีจำนวนเต็ม) ที่มีค่าใช้จ่ายน้อยลง ดังนั้นรายการที่เชื่อมโยงเป็นทวีคูณจึงไม่ทำงานได้ดีกว่าโดยทั่วไป ยิ่งแย่กว่านั้น ประสิทธิภาพเกี่ยวกับประสิทธิภาพของแคชและเวลาแฝงในการจัดสรรหน่วยความจำแบบไดนามิกของรายการนั้นแย่กว่าประสิทธิภาพของอาร์เรย์ / เวกเตอร์เมื่อใช้ตัวจัดสรรเริ่มต้นที่กำหนดโดยสภาพแวดล้อมการนำไปใช้งานพื้นฐาน (เช่น libc) ดังนั้นหากไม่มีความเฉพาะเจาะจงมากนักและ "ชาญฉลาด" รันไทม์อย่างหนักการปรับการสร้างวัตถุเช่นนั้นชนิดอาร์เรย์ / เวกเตอร์จึงเป็นที่ต้องการในรายการที่เชื่อมโยง (ตัวอย่างเช่นการใช้ ISO C ++ มีข้อแม้ว่าstd::vectorควรเป็นที่ต้องการstd::listโดยค่าเริ่มต้น) ดังนั้นการแนะนำดั้งเดิมใหม่ให้กับการสนับสนุน (ทวีคูณ -) รายการที่เชื่อมโยงนั้นไม่เป็นประโยชน์อย่างแน่นอนในการสนับสนุนโครงสร้างข้อมูลอาร์เรย์ / เวกเตอร์ในทางปฏิบัติ

เพื่อความเป็นธรรมรายการยังคงมีคุณสมบัติเฉพาะบางอย่างที่ดีกว่าอาร์เรย์ / เวกเตอร์:

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

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

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

การเปลี่ยนไม่ได้และนามแฝง

ในภาษาบริสุทธิ์เช่น Haskell วัตถุจะไม่เปลี่ยนรูป วัตถุของโครงการมักจะใช้โดยไม่ต้องกลายพันธุ์ ความจริงดังกล่าวทำให้สามารถปรับปรุงประสิทธิภาพของหน่วยความจำได้อย่างมีประสิทธิภาพด้วยการใช้งานวัตถุ - การแบ่งปันโดยนัยของวัตถุหลาย ๆ อันที่มีค่าเหมือนกันในทันที

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

สำหรับวัตถุประสงค์ทั่วไปของการเขียนโปรแกรมตัวเลือกของการออกแบบภาษาอาจมีปัญหา แต่ด้วยรูปแบบการเข้ารหัสการทำงานทั่วไปภาษาดูเหมือนจะยังคงทำงานได้ดี

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