จะตรวจสอบ / พิสูจน์ความถูกต้องของภาษาโปรแกรมได้อย่างไร?


10

ฉันรู้แนวคิดของ orthogonality แต่จากมุมมองภาษาการเขียนโปรแกรมมีวิธีการตรวจสอบ / พิสูจน์หรือไม่

ตัวอย่างเช่นใน C # หนึ่งสามารถใช้publicหรือstaticลายเซ็นวิธี คุณสามารถใช้อย่างใดอย่างหนึ่งหรือทั้งสองและพวกเขาจะไม่รบกวนซึ่งกันและกันดังนั้นพวกเขาจึงมีมุมฉากซึ่งกันและกันใช่มั้ย

คำถามของฉันคือฉันจะไปเกี่ยวกับคุณสมบัติที่เหลือโดยเฉพาะอย่างยิ่งคุณสมบัติที่ไม่เกี่ยวข้องกันได้อย่างไร

คุณสมบัติทั้งหมดต้องอยู่ร่วมกัน / ซ้อนกันหรือไม่?

มีภาษาการเขียนโปรแกรมที่เป็นมุมฉาก 100% หรือไม่?


เริ่มจากจุดเริ่มต้น (ใกล้): ภาษาแอสเซมบลีหรือไม่
Matthew Flynn

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

คำตอบ:


4

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

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

ในแง่นี้ฉันอยากจะตรวจสอบ orthogonality ของCommon Intermediate Languageโดยใช้ภาษา Stack Machine เป็นเป้าหมายสำหรับคอมไพเลอร์ C # ไม่ใช่ C #

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


6

คำว่า "orthogonality" เป็นคำของคนธรรมดาสำหรับความคิดทางคณิตศาสตร์ที่แม่นยำ: เงื่อนไขภาษาเป็นพีชคณิตเริ่มต้น (ดูใน Wikipedia)

มันมีความหมายว่า "มีความสอดคล้อง 1-1 ระหว่างไวยากรณ์และความหมาย" ซึ่งหมายความว่า: มีวิธีหนึ่งที่จะถ่ายทอดสิ่งต่าง ๆ ได้อย่างแน่นอนและหากคุณสามารถแสดงออกบางอย่างในสถานที่หนึ่ง ๆ ได้คุณสามารถใส่การแสดงออกอื่น ๆ ได้เช่นกัน

อีกวิธีที่จะคิดเกี่ยวกับ "orthogonal" คือไวยากรณ์ปฏิบัติตามหลักการทดแทน ตัวอย่างเช่นถ้าคุณมีคำสั่งที่มีช่องสำหรับการแสดงออกแล้วการแสดงออกใด ๆ ที่สามารถวางที่นั่นและผลที่ได้ยังคงเป็นโปรแกรมที่ถูกต้อง syntactically นอกจากนี้หากคุณเปลี่ยน

ฉันต้องการเน้นว่า "ความหมาย" ไม่ได้หมายความถึงผลการคำนวณ เห็นได้ชัดว่า 1 + 2 และ 2 + 1 ทั้งสองเท่ากัน 3 อย่างไรก็ตามข้อกำหนดมีความแตกต่างกันและบ่งบอกถึงการคำนวณที่แตกต่างกันแม้ว่าจะมีผลลัพธ์เหมือนกัน ความหมายแตกต่างกันเนื่องจากอัลกอริทึมการเรียงลำดับสองแบบนั้นแตกต่างกัน

คุณอาจเคยได้ยิน "ต้นไม้ไวยากรณ์นามธรรม" (AST) คำว่า "นามธรรม" ที่นี่หมายถึง "orthogonal" อย่างแม่นยำ ในทางเทคนิคแล้ว AST ส่วนใหญ่นั้นไม่ได้เป็นนามธรรมจริง ๆ !

บางทีคุณเคยได้ยินภาษาการเขียนโปรแกรม "C" หรือไม่ สัญกรณ์ประเภท C ไม่เป็นนามธรรม พิจารณา:

int f(int);

intดังนั้นนี่คือประกาศประเภทฟังก์ชั่นกลับมา ประเภทของตัวชี้ไปยังฟังก์ชั่นนี้ได้รับจาก:

int (*)(int)

หมายเหตุคุณไม่สามารถเขียนประเภทของฟังก์ชั่นได้! สัญกรณ์ประเภท C ดูดครั้งใหญ่! มันไม่เป็นนามธรรม มันไม่ใช่มุมฉาก ทีนี้สมมติว่าเราต้องการสร้างฟังก์ชั่นที่ยอมรับประเภทข้างต้นแทนที่จะเป็น int:

int (*) ( int (*)(int) )

ตกลงทั้งหมด .. แต่ .. ถ้าเราต้องการส่งคืนแทน:

int (*)(int) (*) (int)

woops! โมฆะ ให้เพิ่ม parens:

(int (*)(int)) (*) (int)

woops! ไม่ได้ผลเช่นกัน เราต้องทำสิ่งนี้ (เป็นวิธีเดียว!):

typedef int (intintfunc*) (int);
intintfunc (*)(int)

ตอนนี้ก็โอเค แต่การใช้ typedef ที่นี่ไม่ดี C ดูด มันไม่เป็นนามธรรม มันไม่ใช่มุมฉาก นี่คือวิธีที่คุณทำใน ML ซึ่งคือ:

 int -> (int -> int)

เราประณาม C ที่ระดับไวยากรณ์

ตกลงตอนนี้ให้ flog C ++ เราสามารถแก้ไขความโง่เขลาข้างต้นด้วยเทมเพลตและรับ ML เช่นสัญลักษณ์ (มากหรือน้อย):

fun<int, int>
fun< fun<int,int>, int>

แต่ระบบการพิมพ์จริงมีข้อบกพร่องพื้นฐานโดยอ้างอิง: ถ้าTเป็นประเภทแล้วเป็นT&ประเภท? คำตอบคือ waffly: ที่ระดับไวยากรณ์ถ้าคุณมีประเภท U = T & อนุญาต U & ได้รับอนุญาต แต่มันก็หมายถึง T &: การอ้างอิงถึงการอ้างอิงคือการอ้างอิงเดิม มันแย่มาก! มันแบ่งข้อกำหนดที่เป็นเอกลักษณ์ทางความหมาย แย่ลง: T & & ไม่ได้รับอนุญาต syntactically: นี้ทำลายหลักการทดแทน ดังนั้นการอ้างอิงภาษา C ++ จะแบ่งความเป็นเอกเทศในสองวิธีที่แตกต่างกันขึ้นอยู่กับเวลาในการรวม (การวิเคราะห์คำหรือการวิเคราะห์ประเภท) หากคุณต้องการที่จะเข้าใจวิธีการทำสิ่งนี้ให้ถูกต้อง .. ไม่มีปัญหากับพอยน์เตอร์!

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


คุณคิดว่า ML นั้นมีมุมฉากมากกว่าคนอื่น ๆ ไหม? แล้ว Lisp และ Haskell ล่ะ
Joan Venge

1
@joan: ดีกระเพื่อมไม่ได้มีคุณสมบัติใด ๆ ดังนั้นจึงตอบสนองความต้องการใน vaccuuo :)
Yttrill

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

คุณคิดอย่างไรเกี่ยวกับปาสกาล ดูเหมือนว่าโหลดดีกว่า C.
supercat

ฉันรู้ว่าความคิดเห็นของฉันเกือบ 4 ปีแล้ว แต่ฉันเพิ่งเจอมัน คำตอบนี้ผิดทุกอย่าง แม้แต่ทั้งหมด "เป็นวิธีเดียว!" ส่วนหนึ่งนั้นผิดปกติ คุณสามารถแสดงได้อย่างง่ายดายโดยไม่มีตัวอย่าง typedef int (*intintfunc())(int) { ... }- intintfunc เป็นฟังก์ชั่นที่ไม่มีการขัดแย้งและส่งกลับตัวชี้ไปยังฟังก์ชั่นที่ใช้ 1 int อาร์กิวเมนต์และส่งกลับค่า int
Wiz

4

การพิสูจน์ความฉากมุมฉากคือการพิสูจน์เชิงลบ หมายความว่าคุณไม่มีโครงสร้างที่ไม่ใช่ orthogonal ซึ่งหมายความว่ามันง่ายกว่ามากที่จะพิสูจน์บางสิ่งที่ไม่ใช่ orthogonal มากกว่าที่เป็นอยู่

ในทางปฏิบัติคนส่วนใหญ่พูดถึง orthogonality ของภาษาโปรแกรมในแง่ขององศาแทนที่จะเป็น orthogonal ทั้งหมดหรือไม่ เมื่อความรู้จากการทำบางสิ่งในบริบทหนึ่งแปลไปสู่บริบทอื่นและ "ทำสิ่งที่คุณคาดหวัง" ภาษานั้นกล่าวกันว่าเป็นมุมฉากมากขึ้น LISP ถือได้ว่าเป็นมุมฉากสูงเพราะทุกอย่างเป็นรายการ แต่ฉันไม่คิดว่ามันจะพูดได้ว่าเป็น orthogonal 100% เพราะมีความซ้ำซ้อนบางอย่างที่ทำให้ใช้งานได้ง่ายขึ้น C ++ ถือได้ว่าเป็นมุมฉากไม่มากเพราะมี "gotchas" น้อยมากที่มันไม่ทำงานอย่างที่คุณคิดว่ามันจะ


3

คำเตือนฉันไม่รู้อะไรเกี่ยวกับหัวข้อนี้

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

สำหรับ C # ฉันคิดว่ามันเป็นมุมฉากในกลอุบายส่วนใหญ่ ( foreachนึกถึง) เป็นเพียงส่วนหน้ากับรุ่นที่สร้างขึ้นเป็นพิเศษของโครงสร้างพื้นฐาน ( foreachกลายเป็นforลูป) โดยรวมแล้วภาษาสนับสนุนการทำสิ่งต่าง ๆ อย่างแท้จริงในวิธีเดียวเท่านั้น และท้ายที่สุดมันทั้งหมดรวบรวมลงไปMSIL(หรือสิ่งที่เรียกว่าวันนี้) และMSILมีแนวโน้มตั้งฉาก

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

สองเซ็นต์ของฉัน


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

ไม่do...whileสามารถใช้เพื่อให้ผลเช่นเดียวกับfor? ฉันไม่เคยได้ยินว่ามีการพิจารณาน้ำตาลประโยค
Matthew Flynn

1
@ MatthewFlynn: Bah! มันเป็นน้ำตาลทั้งประโยคคุณสามารถเปลี่ยนการวนซ้ำของคุณด้วยฟังก์ชั่นวนซ้ำ! ;)
FrustratedWithFormsDesigner

2
@FrustratedWithFormsDesigner: นั่นไม่ได้เป็นเพียงน้ำตาล syntactic สำหรับ GOTO หรือไม่?
Ivan

2
@MatthewFlynn do whileรับประกันการประมวลผลลูปเดียวและตรวจสอบสภาพหลังจากข้อเท็จจริง forตรวจสอบสภาพก่อนและไม่รับประกันการใช้งานครั้งเดียว
digitlworld

2

คำถามของฉันคือฉันจะไปเกี่ยวกับคุณสมบัติที่เหลือโดยเฉพาะอย่างยิ่งคุณสมบัติที่ไม่เกี่ยวข้องกันได้อย่างไร

คุณยังคงทำสิ่งที่คุณทำต่อไประบุชุดค่าผสมทั้งหมดที่ทำงานหรือถูกห้าม

นั่นคือทั้งหมดที่ มันค่อนข้างเจ็บปวดที่ต้องทำ

คุณสมบัติทั้งหมดต้องอยู่ร่วมกัน / ซ้อนกันหรือไม่?

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

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

อย่างไรก็ตามบางครั้งมีกรณีพิเศษเนื่องจากระบบปฏิบัติการหรือไลบรารี่ดั้งเดิมที่ไม่ใช่แบบมุมฉาก

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

orthogonal เป็นอย่างไร "orthogonal เพียงพอ"? คุณต้องการเห็นอะไรบ้างที่จะมีความสุขกับระดับของ orthogonality ในภาษาของคุณ


2

รายการคุณสมบัตินอกรีตนั้นใช้เวลานานในการเขียนโปรแกรมภาษาส่วนใหญ่เช่น

  • คลาส anonyous ขัดแย้งกับการสะท้อน Java
  • ข้อขัดแย้งการลบทั่วไปและประเภทที่มีการสะท้อน Java
  • อาร์เรย์ค่อนข้างแตกต่างจากวัตถุอื่น ๆ เนื่องจากเป็นชนิดพิเศษแม้ว่าจะเป็นวัตถุก็ตาม
  • วิธีสแตติกกับอินสแตนซ์นั้นไม่เหมือนกันเช่นคุณไม่สามารถแทนที่เมธอดสแตติกได้
  • ชั้นที่ซ้อนกันเป็นความคิดที่ตามมา
  • ผลกระทบของการพิมพ์แบบไดนามิกและแบบคงที่กับกลยุทธ์การกระจายข้อความ (ดูเช่นกรณีขอบนี้ใน C #)
  • เป็นต้น

นั่นเป็นเพียงบางส่วนที่อยู่ในใจของฉัน แต่มีอีกหลายคนและในภาษาอื่น ๆ

เป็นการยากที่จะตรวจสอบให้แน่ใจว่าไม่มีการรบกวนที่ละเอียดอ่อนระหว่างคุณสมบัติภาษา ดังที่ CAR Hoare ระบุไว้ในบทความ "คำแนะนำในการออกแบบภาษาโปรแกรม":

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

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

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

สิ่งที่น่าสนใจมาก - แต่ก็ท้าทายมาก

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