ทำไมเราถึงใช้โครงสร้างข้อมูลแบบต่อเนื่องในการโปรแกรมเชิงฟังก์ชัน?


22

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


มีการพูดคุยกันอย่างกว้างขวางในเรื่องนี้ใน abelson & sussman โครงสร้างและการแปลความหมายของโปรแกรมคอมพิวเตอร์
vzn

คำตอบ:


19

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

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

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

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

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


นี่ทำให้ฉันมีความรู้สึกมากมาย ขอบคุณที่แบ่งปัน PPT ของคุณ คุณแชร์การบันทึกวิดีโอด้วยเหมือนกันหรือไม่?
gpuguy

@gpuguy ฉันไม่ได้ใช้ powerpoint มากขนาดนั้น ไวท์บอร์ดเป็นสื่อที่ฉันโปรดปราน แต่เอกสารประกอบคำบรรยายควรอ่านได้ด้วยตนเอง
Uday Reddy

+1 คณิตศาสตร์ไม่เคยทำงานกับวัตถุข้อมูลที่ไม่แน่นอน ยังเชื่อมโยงไปยังบันทึกการบรรยายของคุณ
Guy Coder

15

การทำงานกับโครงสร้างข้อมูลถาวรนั้นง่ายกว่าการทำงานกับโครงสร้างข้อมูลที่ไม่แน่นอน นี่ฉันจะบอกว่าเป็นข้อได้เปรียบหลัก

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

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

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


เมื่อมีข้อได้เปรียบมากมายแล้วทำไมไม่ใช้โครงสร้างข้อมูลถาวรในภาษาที่จำเป็นเช่นกัน?
gpuguy

4
บางทีอีกไม่นานคุณจะถามว่า "ทำไมต้องใช้ภาษาที่จำเป็น"
Andrej Bauer

4
แต่อย่างจริงจังมีโครงสร้างข้อมูลที่ยากที่จะแทนที่ด้วยสิ่งที่คงอยู่ตัวอย่างเช่นโปรแกรมการบีบตัวเลขซึ่งใช้อาร์เรย์และเมทริกซ์นั้นเร็วกว่ามากด้วยโครงสร้างข้อมูลแบบดั้งเดิมเพราะฮาร์ดแวร์ได้รับการปรับให้เหมาะกับสิ่งนั้น
Andrej Bauer

1
@gpuguy โครงสร้างข้อมูลถาวรสามารถและควรใช้ในภาษาที่จำเป็นเช่นกันเมื่อใดก็ตามที่เหมาะสมและเหมาะสม เพื่อให้สามารถใช้งานได้ภาษาควรสนับสนุนการจัดการหน่วยความจำแบบอิงขยะ ภาษาที่ทันสมัยหลายแห่งมีเช่น: Java, C #, Scala, Python, Ruby, Javascript และอื่น ๆ
Uday Reddy

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

2

การเพิ่มคำตอบของผู้อื่นและเสริมวิธีการทางคณิตศาสตร์การเขียนโปรแกรมการทำงานยังมีการทำงานร่วมกันที่ดีกับพีชคณิตเชิงสัมพันธ์และการเชื่อมต่อ Galois

สิ่งนี้มีประโยชน์อย่างมากในพื้นที่ของวิธีการแบบเป็นทางการ
ตัวอย่างเช่น

  • การพิสูจน์อย่างเป็นทางการในการตรวจสอบโปรแกรมนั้นง่ายขึ้นด้วย Extended Static Checking;
  • คุณสมบัติจำนวนหนึ่งจาก Relational Algebra มีประโยชน์ในการแก้ SAT ด้วยเครื่องมือเช่น Alloy;
  • การเชื่อมต่อ Galois อนุญาตให้มีวิธีการคำนวณตามข้อกำหนดซอฟต์แวร์ตามที่เห็นในบล็อกนี้โดยมีการอ้างอิงถึงบทความโดย Shin-Cheng Mu และJosé Nuno Oliveira
  • การเชื่อมต่อ Galois (และฟังก์ชั่นการเขียนโปรแกรม) สามารถนำมาใช้ในการออกแบบโดยสัญญาแฟชั่นเนื่องจากพวกเขาเป็นแนวคิดทั่วไปมากกว่า Hoare Logic

ตัวอย่าง

{p}P{q}[P]ϕpϕq[P]

  • [P]P
  • ϕpϕq)pq

วิธีการนี้ยังช่วยให้การคำนวณแบบ pre-condition ที่อ่อนแอที่สุดและแข็งแกร่งที่สุดหลังการเงื่อนไขซึ่งมีประโยชน์ในหลาย ๆ สถานการณ์


2

ฉันต้องการที่จะเข้าใจในระดับต่ำจะเกิดอะไรขึ้นถ้าโครงสร้างข้อมูลไม่คงที่?

ลองดูที่ตัวสร้างตัวเลขเทียมโดยมีพื้นที่ขนาดใหญ่ (เช่น " Mersenne twister " ที่มีสถานะ 2,450 ไบต์) เป็นโครงสร้างข้อมูล เราไม่ต้องการใช้หมายเลขสุ่มใด ๆ มากกว่าหนึ่งครั้งดังนั้นจึงมีเหตุผลเล็กน้อยที่จะใช้สิ่งนี้เป็นโครงสร้างข้อมูลถาวรที่ไม่เปลี่ยนรูป ตอนนี้เรามาถามตัวเองว่ามีอะไรผิดปกติในรหัสต่อไปนี้:

mt_gen = CreateMersenneTwisterPRNGen(seed)
integral = MonteCarloIntegral_Bulk(mt_gen) + MonteCarloIntegral_Boundary(mt_gen)

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

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

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

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


Andrej Bauer ยกประเด็นเรื่อง aliasing สำหรับโครงสร้างข้อมูลที่ไม่แน่นอน น่าสนใจเพียงพอภาษาที่แตกต่างเช่นฟอร์แทรนและซีมีข้อสันนิษฐานที่แตกต่างกันเกี่ยวกับนามแฝงของฟังก์ชันอาร์กิวเมนต์ที่ได้รับอนุญาตและโปรแกรมเมอร์ส่วนใหญ่ไม่ทราบว่าภาษาของพวกเขามีรูปแบบนามแฝงเลย

ความหมายที่เปลี่ยนไม่ได้และความคุ้มค่าอาจ overrated เล็กน้อย สิ่งที่สำคัญกว่านั้นคือประเภทของระบบและกรอบงานเชิงตรรกะ (เช่นโมเดลเครื่องนามธรรม, โมเดลนามแฝง, โมเดลการทำงานพร้อมกันหรือโมเดลการจัดการหน่วยความจำ) ของภาษาโปรแกรมของคุณให้การสนับสนุนที่เพียงพอสำหรับการทำงาน "ปลอดภัย" ด้วยข้อมูล "ประสิทธิภาพ" โครงสร้าง การแนะนำของ "การย้ายความหมาย" ไปที่ C ++ 11 อาจดูเหมือนขั้นตอนใหญ่ในแง่ของความบริสุทธิ์และ "ความปลอดภัย" จากมุมมองทางทฤษฎี แต่ในทางปฏิบัติมันตรงกันข้าม ระบบประเภทและกรอบการทำงานของภาษาได้ถูกขยายออกไปเพื่อกำจัดส่วนใหญ่ของอันตรายที่เกี่ยวข้องกับความหมายใหม่ (และแม้ว่าขอบที่ขรุขระยังคงอยู่นั่นไม่ได้หมายความว่า "ดีกว่า" นี้ไม่สามารถปรับปรุงได้


Uday Reddy ยกประเด็นที่คณิตศาสตร์ไม่เคยทำงานกับวัตถุข้อมูลที่ไม่แน่นอนและระบบประเภทสำหรับโปรแกรมการทำงานได้รับการพัฒนาอย่างดีสำหรับวัตถุข้อมูลที่ไม่เปลี่ยนรูป สิ่งนี้ทำให้ฉันนึกถึงคำอธิบายของ Jean-Yves Girard ว่าคณิตศาสตร์ไม่ได้ใช้ในการทำงานกับวัตถุที่เปลี่ยนแปลงได้เมื่อเขาพยายามกระตุ้นตรรกะเชิงเส้น

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


@DW คุณอาจถูกต้องว่าคำตอบนี้ไม่ใช่คำตอบแบบสแตนด์อะโลน ปัจจุบันนี้มีเพียงบางประเด็นที่เพิ่มขึ้นในคำตอบของ Uday Reddy และ Andrej Bauer ฉันคิดว่าฉันสามารถแก้ไขมันให้อยู่คนเดียวและตอบ "ฉันต้องการเข้าใจในระดับต่ำจะเกิดอะไรขึ้นถ้าโครงสร้างข้อมูลไม่คงอยู่?" ส่วนหนึ่งของคำถาม ฉันจะดูเครื่องกำเนิดเลขเทียมโดยมีพื้นที่ขนาดใหญ่ (เช่น "Mersenne twister" ที่มี 2,400 ไบต์รัฐ) เป็นโครงสร้างข้อมูลและอธิบายสิ่งที่ผิดพลาด
Thomas Klimpel

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