มีการจัดการผลข้างเคียงในความหมายอย่างไร


19

ในส่วน"รู้เบื้องต้นเกี่ยวกับการเขียนโปรแกรมภาษา"ของ Anthony Aaby ในอรรถศาสตร์เขาทำการสังเกตต่อไปนี้:

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

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

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


ควรติดแท็กเป็นคำถามแบบอ่อนหรือไม่ เนื่องจาก "งานส่วนใหญ่ในความหมาย [... ] ได้รับแรงบันดาลใจจาก [ผลข้างเคียง]" แน่นอนคุณไม่สามารถคาดหวังคำตอบสั้น ๆ และเข้มงวดได้
Radu GRIGore

1
@Radu: ใน MO นี้อาจจะติดแท็ก [ภาพใหญ่] ซึ่งส่วนใหญ่ไม่ใช่ [คำถามอ่อน] หรือ CW ที่นั่น
Charles Stewart

แท็กภาพใหญ่ดียิ่งขึ้น ฉันลืมไปแล้ว
Radu GRIGore

คำแนะนำที่ดี; ฉันเพิ่มแท็ก
เชน

คำตอบ:


18

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

Object x = new Object();
Object y = new Object();
... some more code ...

ดังนั้นโปรแกรมนี้สร้างวัตถุและตั้งชื่อเป็น x จากนั้นสร้างวัตถุที่สองที่ชื่อ y แล้วดำเนินการโค้ดเพิ่มเติมอีก ทีนี้สมมติว่าโปรแกรมเมอร์ตัดสินใจที่จะพลิกลำดับการจัดสรรของวัตถุทั้งสองนี้:

Object y = new Object();
Object x = new Object();
... some more code ...

ตอนนี้ถามคำถาม: การเปลี่ยนโครงสร้างใหม่นี้เปลี่ยนพฤติกรรมของโปรแกรมหรือไม่ ในอีกด้านหนึ่งบนเครื่องต้นแบบ x และ y จะได้รับการจัดสรรในสถานที่ต่าง ๆ ในการรันโปรแกรมสองครั้ง ดังนั้นในแง่นี้โปรแกรมทำงานต่างกัน

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

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

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

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


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

1
โดย "ไคลเอนต์ของ X" ฉันหมายถึงเหมือนกับ "บริบทของโปรแกรม" ซึ่งเป็นเพียง "โปรแกรมที่มีขนาดใหญ่กว่าซึ่งมี X เป็น subterm"
Neel Krishnaswami

ดังนั้นคุณใช้ 'X เป็นไคลเอนต์ของ Y' สลับกันได้กับ 'X อ่าน Y เป็นอินพุต' เพราะคุณคิดว่า X เป็นแลมบ์ดาที่ใช้กับ Y? มันสมเหตุสมผล แต่มันบิดเบี้ยวเล็กน้อยเมื่อคุณพูดถึง Java :)
Radu GRIGore

1
@RaduGRIGore: บริบทโปรแกรมหมายถึงอย่างอื่น คุณกำลังอ่านโพสต์อย่างถูกต้อง แต่ถ้า X อ่านซอร์สโค้ดของ Y เป็นอินพุต (ซึ่งเป็นวิธีที่ฉันตีความโพสต์) คุณสามารถแยกแยะโปรแกรมที่แตกต่างกันของ syntactically ทุกสองโปรแกรม; หาก Y เป็นฟังก์ชัน lambda บน X คุณสามารถแยกความแตกต่างของโปรแกรมน้อยเกินไป ความคิดเห็นของ Neel เกี่ยวกับ "บริบทของโปรแกรม" เป็นคำจำกัดความที่ถูกต้อง: บริบทของโปรแกรม Y เป็นโปรแกรมที่มีรูใน AST ซึ่งคุณสามารถวาง (ความหมาย) โปรแกรมย่อยสองส่วนที่แตกต่างกัน X1 และ X2
Blaisorblade

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

12

มีวิธีที่แน่นอนในการจัดการกับผลกระทบในความหมาย (denotational) ตัวอย่างเช่นเราสามารถใช้ความคิดของ Eugenio Moggiว่าเอฟเฟ็กต์การคำนวณเป็น monads (ความคิดนี้ยังถูกใช้ในการออกแบบ Haskell ด้วย) ปัญหาอย่างหนึ่งของเรื่องนี้ก็คือการที่พระผสมยาก Gordon PlotkinและJohn Powerแนะนำให้ปรับแต่ง monads ของ Moggi เพื่อ Lawvere ทฤษฎีหรือทฤษฎีเกี่ยวกับพีชคณิตตามที่พวกเขาเรียกว่าซึ่งครอบคลุมผลเกี่ยวกับพีชคณิต (ผลกระทบที่พบบ่อยที่สุดคือพีชคณิตเช่นสถานะ I / O ไม่ใช่การกำหนด ไม่). สำหรับการรักษาที่ครอบคลุมดูวิทยานิพนธ์ Matija Pretnar ของ

ฉันควรจะพูดถึงความหมายของโลกที่เป็นไปได้สำหรับรัฐในท้องถิ่นที่พัฒนาโดย Frank Oles และJohn Reynolds (ขออภัยไม่สามารถหาลิงค์ที่ดีกว่าได้สิ่งนี้มาจากปี 1982) ซึ่งถือกำเนิดขึ้นจากพระของ Moggi พวกเขาใช้หมวดหมู่ของ presheaves เพื่อให้ความหมายของภาษาที่เหมือน algol ซึ่งเป็นแบบอย่างที่ถูกต้องหลายแง่มุมของสภาพท้องถิ่น (แต่ไม่ใช่ทั้งหมดของพวกเขาฉันคิดว่ารูปแบบอนุญาต snapback แต่บางทีความทรงจำของฉันทำหน้าที่ฉันผิด)


1
ใช่ความหมายหมวด functor ไม่ได้ตรวจสอบการเทียบเท่า Meyer-Sieber ทั้งหมด Peter O'Hearn และ Robert Tennant ได้พัฒนาซีแมนทิกส์ประเภท functor ในช่วงกลางทศวรรษที่ 90 ซึ่ง (IIRC) ได้รับตัวอย่างของ Meyer-Sieber ทั้งหมด แต่ฉันไม่รู้ว่ามันเป็นนามธรรมอย่างสมบูรณ์หรือไม่
Neel Krishnaswami

โมเดลของ O'Hearn และ Tennent นั้นไม่เป็นนามธรรมอย่างสมบูรณ์ ที่กล่าวถึงในบทความนั้นเอง แต่การปรับแต่งโดย O'Hearn และ Reynolds โดยใช้แคลคูลัสแลมบ์ดาเชิงเส้นนั้นมีความเป็นนามธรรมอย่างสมบูรณ์ถึงลำดับที่สอง มันแบ่งสำหรับลำดับที่สามตัวอย่างคือความเท่าเทียมที่ศึกษาโดย Ahmed, Dreyer, Birkedal และคณะ
Uday Reddy

12

Matthias Felleisen นำเสนอทางออกที่น่าสนใจสำหรับปัญหาผลข้างเคียงในซีแมนทิกส์ในซีรีส์ของเขาในหัวข้อ "ทฤษฎีการควบคุมและรัฐ"

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

เครื่อง CESK และความหมายการดำเนินงานขั้นตอนเล็ก ๆ ในวงกว้างมากขึ้นเป็นมาตรฐานที่แท้จริงในทฤษฎีภาษาโปรแกรมมาประมาณสองทศวรรษ

ในระยะสั้นเครื่อง CESK เป็นเครื่องขนาดเล็กที่มีส่วนประกอบสี่อย่างเพื่ออธิบายสถานะของเครื่องทุกอัน: สตริงควบคุม (การวางนัยทั่วไปของตัวนับโปรแกรม), สภาพแวดล้อม, ร้านค้า (หรือที่เรียกว่าฮีป) และความต่อเนื่องในปัจจุบัน

สภาพแวดล้อมแผนที่ตัวแปรที่อยู่; ร้านค้าแผนที่ที่อยู่กับค่า

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

นอกจากนี้ยังทำให้ง่ายต่อการจำลองพอยน์เตอร์และการจัดสรรแบบไดนามิก: เพียงแค่ทำให้ที่อยู่ร้านค้าเป็นค่าชั้นหนึ่ง

ในทำนองเดียวกันความต่อเนื่องชั้นหนึ่งเป็นผลมาจากการทำให้พวกเขามีค่าที่อยู่


6

การมีอยู่ของผลข้างเคียงในภาษาการเขียนโปรแกรมส่งผลกระทบต่อความสามารถในการแมปโปรแกรมกับโมเดลการคำนวณอย่างไร

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

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

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

มีวิธีการในการจัดการสถานะที่สามารถปรับปรุงกระบวนการนี้ในขณะที่ยังให้ผลข้างเคียงหรือไม่?

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


PCF ของ Scott ไม่มีสถานะและไม่ใช่ของ Scott ใช่หรือไม่ดูen.wikipedia.org/wiki/ …
Andrej Bauer

@ Andrej: เอ่อค่อนข้างเนื่องจากลุคองค์ดูแล D.Phil ของฉันฉันไม่ควรทำผิดพลาด ฉันโพสต์สรุปโดยย่อของ PCF ของมิลเนอร์และ LCF ของสก็อตต์ที่มากกว่า ... ประสบความสำเร็จมากกว่า WP เป็นเรื่องราวของLtU : lambda-the-ultimate.org/node/2196 เกิดขึ้นกับฉันว่าคุณอาจเข้าถึง Scott ที่หายไป (1969) ต้นฉบับ ...
ชาร์ลส์สจ๊วต

นั่นจะเป็น PCF ของ Plotkin ฉันคิดว่า :-) ฉันสามารถพยายามเก็บต้นฉบับ แต่จริงๆแล้วฉันไม่มีมัน
Andrej Bauer

แต่ประเด็นยังคงอยู่ที่ PCF ไม่มีสถานะ "เหตุผล" อะไรที่คุณกำลังบอกว่า Strachey จะประณามความหมายในการดำเนินงาน? สำหรับฉันมันไม่ชัดเจน ย่อหน้าสุดท้ายขัดแย้งกับสิ่งที่คุณพูดก่อนหน้านี้กล่าวคือคำสั่งที่มีการป้องกันมีความหมายที่ดี แต่ PCF ไม่ได้!
Uday Reddy

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