มีภาษาที่ใช้งานได้ซึ่งอนุญาตให้ใช้ความหมายของสแต็ก - การทำลายที่กำหนดขึ้นโดยอัตโนมัติเมื่อสิ้นสุดขอบเขตหรือไม่?
มีภาษาที่ใช้งานได้ซึ่งอนุญาตให้ใช้ความหมายของสแต็ก - การทำลายที่กำหนดขึ้นโดยอัตโนมัติเมื่อสิ้นสุดขอบเขตหรือไม่?
คำตอบ:
ไม่ใช่ที่ฉันรู้ แต่ฉันไม่เชี่ยวชาญการเขียนโปรแกรมทำงาน
ดูเหมือนว่าค่อนข้างยากในหลักการเนื่องจากค่าที่ส่งคืนจากฟังก์ชันอาจมีการอ้างอิงถึงค่าอื่น ๆ ที่สร้างขึ้น (บนสแต็ก) ภายในฟังก์ชันเดียวกันหรืออาจส่งผ่านได้ง่ายเช่นเดียวกับพารามิเตอร์หรืออ้างอิงโดยบางสิ่งที่ส่งผ่าน เป็นพารามิเตอร์ ใน C ปัญหานี้ได้รับการจัดการโดยการอนุญาตให้ตัวชี้ห้อย (หรือแม่นยำมากขึ้นพฤติกรรมที่ไม่ได้กำหนด) อาจเกิดขึ้นได้หากโปรแกรมเมอร์ไม่ได้รับสิ่งที่ถูกต้อง นั่นไม่ใช่วิธีการแก้ปัญหาที่นักออกแบบภาษาที่ใช้งานได้อนุมัติ
มีวิธีแก้ปัญหาที่อาจเกิดขึ้นได้ แนวคิดหนึ่งคือการทำให้อายุการใช้งานของค่าเป็นส่วนหนึ่งของชนิดของค่าพร้อมกับการอ้างอิงถึงและกำหนดกฎตามประเภทที่ป้องกันไม่ให้คืนค่าการจัดสรรสแต็กจากการส่งคืนหรืออ้างอิงโดยสิ่งที่ส่งคืนมา ฟังก์ชัน ฉันไม่ได้ทำงานผ่านความหมาย แต่ฉันคิดว่ามันน่ากลัว
สำหรับรหัส monadic ก็มีอีกวิธีหนึ่งซึ่งก็คือ monadic (อันที่จริงหรือเกือบจะเหมือนกัน) และสามารถให้ IORef ที่ถูกทำลายลงโดยอัตโนมัติ หลักการคือการกำหนดการกระทำ "ซ้อน" เมื่อรวมกัน (โดยใช้โอเปอเรเตอร์เชื่อมโยง) สิ่งเหล่านี้จะกำหนดโฟลว์การควบคุมการซ้อน - ฉันคิดว่า "องค์ประกอบ XML" ด้วยค่าซ้ายสุดของการจัดหาคู่เริ่มต้นและแท็กด้านนอก "แท็ก XML" เหล่านี้เป็นเพียงการกำหนดการเรียงลำดับของการกระทำแบบ monadic ที่ระดับที่เป็นนามธรรม
ในบางจุด (ที่ด้านขวามือของสายโซ่ของการรวมกลุ่มที่เชื่อมโยงกัน) คุณจำเป็นต้องมีเทอร์มิเนเตอร์บางอย่างเพื่อวางรัง - บางอย่างเพื่อเติมเต็มรูตรงกลาง ความจำเป็นในการใช้เทอร์มิเนเตอร์คือสิ่งที่อาจหมายถึงว่าโอเปอเรเตอร์การซ้อนจะไม่ได้เป็นแบบ monadic แต่ฉันก็ไม่แน่ใจเหมือนกันเพราะฉันยังไม่ได้ทำงานให้ละเอียด เนื่องจากการประยุกต์ใช้เทอร์มิเนเตอร์นั้นจะทำการแปลงการซ้อนในรูปแบบการกระทำแบบ monadic ปกติที่มีประสิทธิภาพอาจจะไม่ - มันไม่จำเป็นต้องส่งผลกระทบต่อตัวดำเนินการเรียงซ้อน
การกระทำพิเศษเหล่านี้หลายอย่างอาจมีขั้นตอน "แท็กปิดท้าย" ที่เป็นโมฆะและจะดำเนินการตามขั้นตอน แต่บางคนก็เป็นตัวแทนของการประกาศตัวแปร สิ่งเหล่านี้จะเป็นตัวแทนของตัวสร้างที่มีแท็กเริ่มต้นและ destructor ที่มีแท็กสิ้นสุด คุณได้อะไรเช่น ...
act = terminate ((def-var "hello" ) >>>= \h ->
(def-var " world") >>>= \w ->
(use-val ((get h) ++ (get w)))
)
การแปลเป็นองค์ประกอบแบบ monadic ที่มีลำดับการดำเนินการต่อไปนี้แต่ละแท็ก (ไม่ใช่องค์ประกอบ) กลายเป็นการกระทำแบบ monadic ปกติ ...
<def-var val="hello"> -- construction
<def-var val=" world> -- construction
<use-val ...>
<terminator/>
</use-val> -- do nothing
</def-val> -- destruction
</def-val> -- destruction
กฎเช่นนี้อาจทำให้ C ++ - สไตล์ RAII สามารถใช้งานได้ การอ้างอิงที่คล้ายกันของ IORef ไม่สามารถหลบหนีขอบเขตของพวกเขาได้ด้วยเหตุผลที่คล้ายกันว่าทำไม IORef ปกติไม่สามารถหลบหนี Monad ได้ - กฎขององค์ประกอบการเชื่อมโยงนั้นไม่มีทางสำหรับการอ้างอิงเพื่อหลบหนี
แก้ไข - ฉันเกือบลืมบอกว่า - มีพื้นที่แน่นอนฉันไม่แน่ใจเกี่ยวกับที่นี่ สิ่งสำคัญคือต้องแน่ใจว่าตัวแปรภายนอกไม่สามารถอ้างอิงตัวแปรภายในได้ดังนั้นต้องมีข้อ จำกัด หนึ่งสิ่งที่คุณสามารถทำได้กับการอ้างอิงแบบ IORef เหล่านี้ อีกครั้งฉันไม่ได้ทำงานผ่านรายละเอียดทั้งหมด
ดังนั้นการก่อสร้างสามารถเปิดไฟล์ที่ทำลายได้ การก่อสร้างสามารถเปิดซ็อกเก็ตที่ทำลายปิด โดยพื้นฐานแล้วใน C ++ ตัวแปรจะกลายเป็นตัวจัดการทรัพยากร แต่แตกต่างจาก C ++ ไม่มีวัตถุที่จัดสรรฮีปที่ไม่สามารถทำลายได้โดยอัตโนมัติ
แม้ว่าโครงสร้างนี้รองรับ RAII คุณยังต้องมีตัวรวบรวมขยะ แม้ว่าการกระทำที่ซ้อนกันสามารถจัดสรรและเพิ่มหน่วยความจำให้ถือว่าเป็นทรัพยากร แต่ก็ยังมีการอ้างอิงทั้งหมดถึงค่าที่ใช้ในการทำงาน (อาจแชร์) ภายในหน่วยความจำอันนั้นและที่อื่น ๆ เนื่องจากหน่วยความจำสามารถจัดสรรได้อย่างง่ายดายบนสแต็กโดยไม่จำเป็นต้องใช้ฮีพฟรีความสำคัญจริง (ถ้ามี) สำหรับการจัดการทรัพยากรประเภทอื่น
ดังนั้นสิ่งนี้ประสบความสำเร็จคือการแยกการจัดการทรัพยากรสไตล์ RAII จากการจัดการหน่วยความจำอย่างน้อยในกรณีที่ RAII ขึ้นอยู่กับขอบเขตการซ้อนง่าย คุณยังต้องการตัวเก็บรวบรวมขยะสำหรับการจัดการหน่วยความจำ แต่คุณจะได้รับการทำความสะอาดอย่างอัตโนมัติและกำหนดเวลาโดยอัตโนมัติเกี่ยวกับทรัพยากรอื่น ๆ
shared_ptr<>
) คุณยังคงถูกทำลายอย่างต่อเนื่อง สิ่งหนึ่งที่เป็นเรื่องยากสำหรับ RAII คือการอ้างอิงแบบวนรอบ RAII ทำงานได้อย่างหมดจดหากกราฟความเป็นเจ้าของเป็นกราฟ Acyclic โดยตรง
หากคุณคิดว่า C ++ เป็นภาษาที่ใช้งานได้ (มี lambdas) แสดงว่าเป็นตัวอย่างของภาษาที่ไม่ได้ใช้การรวบรวมขยะ
ฉันต้องบอกว่าคำถามนั้นค่อนข้างชัดเจนเพราะถือว่ามีคอลเลกชันมาตรฐานของ "ภาษาที่ใช้งานได้" เกือบทุกภาษาการเขียนโปรแกรมรองรับการเขียนโปรแกรมการทำงานบางส่วน และเกือบทุกภาษาการเขียนโปรแกรมรองรับการเขียนโปรแกรมที่จำเป็นจำนวนหนึ่ง ไม่มีใครวาดเส้นที่จะพูดซึ่งเป็นภาษาที่ใช้งานได้และซึ่งเป็นภาษาที่จำเป็นนอกเหนือจากอคติทางวัฒนธรรมและความเชื่อที่นิยม?
วิธีที่ดีกว่าในการตั้งคำถามคือ "เป็นไปได้หรือไม่ที่จะสนับสนุนการตั้งโปรแกรมการทำงานในหน่วยความจำที่จัดสรรไว้" คำตอบก็คือยากมาก รูปแบบการเขียนโปรแกรมการทำงานส่งเสริมการจัดสรรโครงสร้างข้อมูลซ้ำตามความประสงค์ซึ่งต้องใช้หน่วยความจำฮีป (ไม่ว่าจะเป็นการรวบรวมขยะหรือการอ้างอิง) อย่างไรก็ตามมีเทคนิคการวิเคราะห์คอมไพเลอร์ที่ซับซ้อนที่เรียกว่าการวิเคราะห์หน่วยความจำตามภูมิภาคซึ่งคอมไพเลอร์สามารถแบ่งฮีปเป็นบล็อกขนาดใหญ่ที่สามารถจัดสรรและยกเลิกการจัดสรรโดยอัตโนมัติในลักษณะที่คล้ายกับการจัดสรรสแต็ก หน้า Wikipedia แสดงรายการการนำเทคนิคไปใช้งานที่หลากหลายทั้งสำหรับภาษาที่ "ใช้งานได้" และ "จำเป็น"