ความฝันของการเขียนโปรแกรมที่เปิดเผย [ปิด]


26

ทำไมความฝันของการเขียนโปรแกรมเชิงประกาศไม่ได้ถูกรับรู้? อะไรคืออุปสรรคคอนกรีตที่ขวางทาง? ยกตัวอย่างง่ายๆทำไมฉันพูดไม่ได้

sort(A) is defined by sort(A) in perm(A) && asc(sort(A))

และรับอัลกอริธึมการเรียงลำดับโดยอัตโนมัติ permหมายถึงการเรียงสับเปลี่ยนและascหมายถึงการเพิ่มขึ้น


4
โดยวิธีการที่ตัวอย่างที่เฉพาะเจาะจงของคุณเป็นประเภทที่มีอยู่แล้ว: gkoberger.github.io/stacksort
Den

3
คุณเคยได้ยินภาษาโปรล็อกไหม? เพียงมองหา "Answer Set Programming" มีระบบจำนวนมากที่สร้างขึ้นตามตรรกะเริ่มต้น
schlingel

16
คำถามนี้ตอบง่าย พยายามที่จะใช้ระบบดังกล่าว อะไรทำให้คุณไม่ประสบความสำเร็จ เป็นสิ่งที่ดีที่สิ่งที่หยุดคุณได้หยุดคนอื่นไว้
Eric Lippert

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

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

คำตอบ:


8

มีคำตอบที่ดีมาก ฉันจะพยายามมีส่วนร่วมในการอภิปราย

ในหัวข้อของการประกาศการเขียนโปรแกรมเชิงตรรกะใน Prolog มีหนังสือที่ดี "หัตถกรรมของเปิดฉาก" โดยริชาร์ดโอคีฟ มันเกี่ยวกับการเขียนโปรแกรมที่มีประสิทธิภาพโดยใช้ภาษาการเขียนโปรแกรมที่ช่วยให้คุณเขียนโปรแกรมที่ไม่มีประสิทธิภาพมาก ในหนังสือเล่มนี้ในขณะที่พูดถึงการใช้งานที่มีประสิทธิภาพของอัลกอริทึมหลาย (ในบท "วิธีการเขียนโปรแกรม") ผู้เขียนใช้วิธีการดังต่อไปนี้:

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

การสังเกตที่แจ่มแจ้งที่สุด (สำหรับฉัน) ฉันสามารถทำในขณะที่ทำงานทางของฉันผ่านสิ่งเหล่านี้:

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

กล่าวอีกนัยหนึ่งในขณะที่ใช้งานโซลูชันเราได้ใช้ความรู้เกี่ยวกับปัญหามากที่สุดเท่าที่จะทำได้ เปรียบเทียบ:

ค้นหาการเรียงลำดับของรายการที่องค์ประกอบทั้งหมดอยู่ในลำดับจากน้อยไปหามาก

ที่:

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

เล็ก ๆ น้อย ๆ : ความหมายเหมือนที่คุณให้ไว้เป็นที่น่าสนใจเพราะมันเป็นเรื่องทั่วไปมาก อย่างไรก็ตามฉันไม่สามารถหลบหนีจากความรู้สึกที่ตั้งใจเพิกเฉยต่อความจริงที่ว่าการเรียงสับเปลี่ยนนั้นเป็นปัญหา combinatorial นี่คือสิ่งที่เรารู้อยู่แล้ว! นี่ไม่ใช่การวิจารณ์เพียงแค่การสังเกต

สำหรับคำถามจริง: จะก้าวไปข้างหน้าอย่างไร วิธีหนึ่งคือการให้ความรู้มากเกี่ยวกับปัญหาที่เราประกาศกับคอมพิวเตอร์

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

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

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

PS

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

last(List, Last) :-
    append(_, [Last], List).

ที่นี่ความหมายที่เปิดเผยของappend/3คือ:

List1AndList2คือการต่อกันของList1และList2

เนื่องจากในอาร์กิวเมนต์ที่สองที่append/3เรามีรายการที่มีเพียงองค์ประกอบเดียวและอาร์กิวเมนต์แรกจะถูกละเว้น (ขีดล่าง) เราจะได้รับการแยกรายการเดิมซึ่งแยกหน้ารายการ ( List1ในบริบทของappend/3) และเรียกร้องให้ ด้านหลัง ( List2ในบริบทของappend/3 ) เป็นรายการที่มีองค์ประกอบเดียวเท่านั้น: ดังนั้นจึงเป็นองค์ประกอบสุดท้าย

อย่างไรก็ตามการใช้งานจริงโดย SWI-Prologกล่าวว่า:

last([X|Xs], Last) :-
    last_(Xs, X, Last).

last_([], Last, Last).
last_([X|Xs], _, Last) :-
    last_(Xs, X, Last).

นี่คือการประกาศอย่างดี อ่านจากบนลงล่างพูดว่า:

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

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

last(List, Last) :-
    reverse(List, [Last|_]).

องค์ประกอบสุดท้ายของรายการคือองค์ประกอบแรกของรายการที่กลับรายการ

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


2
+1 สำหรับการแสดงว่าการออกแบบเชิงประกาศสามารถดำเนินไปได้อย่างไรจากสิ่งที่เป็นนามธรรมอย่างง่ายไปจนถึงการใช้งานที่เป็นรูปธรรมมากขึ้นผ่านกระบวนการออกแบบซ้ำ
itsbruce

1
@ Boris นี่เป็นคำตอบที่ดี หนังสือเล่มนั้นนั่งอยู่บนชั้นหนังสือของฉัน อาจถึงเวลาที่ฉันเปิดมัน
davidk01

1
@ davidk01 หนึ่งในหนังสือที่ดีกว่าออกมา ถือว่าคุณค่อนข้างสบายใจกับ Prolog และการเขียนโปรแกรมโดยทั่วไป แต่วิธีการที่ใช้ในการเขียนโปรแกรมนั้นมีทั้งในทางปฏิบัติและทั่วถึง
XXX

2
@ Boris ฉันรู้ว่าตัวอย่างนั้นไม่ซับซ้อน แต่ประสิทธิภาพของกระบวนการออกแบบซ้ำ - ความแข็งแกร่งที่แท้จริงของภาษาที่ประกาศ - และมันมีคุณค่ามากในการฝึกฝน ภาษาที่เปิดเผยให้ชัดเจนสอดคล้องrecursiveแนวทางการปรับปรุง Herre ซ้ำ ภาษาที่ไม่จำเป็นต้องทำ
itsbruce

1
+1 สำหรับ "รับการอภิปรายที่ไม่สามารถสรุปได้ของคุณเกี่ยวกับสิ่งที่ดีการเปิดฉากเชิงประกาศ" ... จริงมากที่เราไม่เห็นด้วย!
Daniel Lyons

50

ภาษาเชิงตรรกะทำสิ่งนี้แล้ว คุณสามารถกำหนดการเรียงลำดับคล้ายกันกับที่คุณทำ

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

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

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


6
มันอาจช่วยให้รู้ว่าคำว่าโกเลมגולםหมายถึง "วัตถุดิบ" คือสถานะพื้นฐานที่สุดที่เครื่องจักร / เอนทิตีสามารถอยู่ได้
dotancohen

2
ภาษาที่ประกาศไม่ได้เป็นอุปสรรคต่อการลดระดับของสิ่งที่เป็นนามธรรม Haskell และ Standard ML ทั้งสองวิธีสามารถช่วยให้คุณสร้างคำแถลงการณ์ที่เรียบง่ายเกี่ยวกับประเภท / ฟังก์ชั่นในที่เดียวให้ช่วงของการใช้งานที่เป็นรูปธรรมและฟังก์ชั่นที่เฉพาะเจาะจงในสถานที่ที่แยกต่างหาก ในขณะเดียวกันแนวปฏิบัติที่ดีที่สุดในภาษา OO / ความจำเป็นขณะนี้เป็นอย่างมากเกี่ยวกับการเริ่มต้นที่สูง / ง่ายแล้วเพิ่มรายละเอียดการใช้งาน ความแตกต่างคือสิ่งที่เป็นนามธรรมสูงง่ายกว่าใน FP ระดับต่ำนั้นง่ายกว่า
itsbruce

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

22
@BAR Golem! = Golum Golem มาจากนิทานพื้นบ้านของชาวยิว
Euphoric

10
Takeaway ของฉันจากคำตอบนี้คือการเขียนאמתบนแล็ปท็อปของฉัน
Dan J

45

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

  • HTML ประกาศว่าเนื้อหาของหน้าเว็บคืออะไร

  • CSS ประกาศว่าองค์ประกอบประเภทต่างๆในหน้าเว็บควรมีหน้าตาเป็นอย่างไร

  • ทุกฐานข้อมูลเชิงสัมพันธ์มีภาษานิยามข้อมูลที่ประกาศว่าโครงสร้างของฐานข้อมูลคืออะไร

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

  • หนึ่งอาจยืนยันว่าไฟล์การกำหนดค่าส่วนใหญ่ (.vimrc, .profile, .bashrc, .gitconfig) กำลังใช้ภาษาเฉพาะโดเมนที่มีการประกาศส่วนใหญ่


3
ฉันจะพูดถึง GNU Make, XSLT, Angular.js เป็นสิ่งที่ใช้กันอย่างแพร่หลายซึ่งเป็นสิ่งที่ประกาศด้วย (ถึงแม้ว่าเชิงมุมอาจผลักดันนิยามเล็กน้อย)
Mark K Cowan

ให้ฉันเพิ่มนิพจน์ทั่วไปในรายการนั้น
Schwern

7
ผู้คนมักจะลืมว่าภาษาที่เปิดเผยเป็นเรื่องธรรมดา โดยทั่วไปแล้วพวกเขาไม่ได้พูดภาษาที่สมบูรณ์ เพิ่ม regex ลงในรายการ
slebetman

ค่อนข้างกระฉับกระเฉง แต่ก็ยัง: ไม่ใช่ทุกฐานข้อมูลที่มี DDL เพียงแค่คิดถึงฐานข้อมูล NoSQL จำนวนมาก ทุกความสัมพันธ์ของฐานข้อมูลอาจจะมี แต่ไม่ทุกฐานข้อมูล
Reinstate Monica - dirkk

1
@dirkk ไม่ได้คิดอย่างนั้น แก้ไขคำตอบของฉัน
Ixrec

17

บทคัดย่อมีการรั่วไหล

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

ในตัวอย่างเฉพาะของคุณคุณจะได้รับขั้นตอนวิธีการเรียงลำดับ - มันไม่ได้หมายความว่าคุณจะได้รับสิ่งที่ดีหรือแม้กระทั่งการใช้งานค่อนข้างหนึ่ง คำนิยามของคุณหากนำไปใช้อย่างแท้จริง (ตามที่มีแนวโน้มว่าคอมไพเลอร์) จะส่งผลให้เกิดhttp://en.wikipedia.org/wiki/Bogosortซึ่งไม่สามารถใช้ได้สำหรับชุดข้อมูลขนาดใหญ่ - มันถูกต้องทางเทคนิค แต่ต้องการนิรันดร์เพื่อเรียงตัวเลข .

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


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

3
Peters ไม่ได้บอกว่าประสิทธิภาพที่ไม่ดีนั้นเป็นสัญญาณของนามธรรมที่น่ารำคาญ @valenterry ถ้ามีอะไรเขากำลังพูดตรงกันข้าม: เพื่อให้ได้ผลงานที่ดีรายละเอียดการใช้งานจะถูกบังคับให้รั่วไหล
itsbruce

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

1
@jamesqf ในการเขียนโปรแกรมเชิงประกาศคุณเพียงแค่ระบุว่ามีบางอย่างที่เรียงลำดับ คุณสามารถประกาศให้เรียงลำดับถูกผูกไว้กับตัวแปร / คุณสมบัติบางอย่าง แล้วมันจะเป็นเช่นนั้น ไม่จำเป็นต้องโทรจัดเรียงอย่างชัดเจนทุกครั้งที่มีการเพิ่มข้อมูลใหม่หรือเรียงลำดับการเปลี่ยนแปลง
hyde

1
@jamesqf คุณไม่สามารถเห็นจุดจริงโดยไม่ลองตัวเอง (ฉันขอแนะนำ QML ของ Qt สำหรับเล่นกับความคิดที่เปิดเผย) ลองนึกภาพใครบางคนที่รู้แค่การเขียนโปรแกรมที่จำเป็นและพวกเขาพยายามที่จะเข้าใจจุดของ OOP หรือการเขียนโปรแกรมการทำงานโดยไม่ต้องลองใช้จริง
hyde

11

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

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

ฉันต้องการตรวจสอบเรื่องนี้กับบางโดเมนที่เป็นที่รู้จักกันดี

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

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

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

ผลก็คือภาวะแทรกซ้อนเหล่านี้เริ่มต้นด้วยความประหลาดใจพวกเขาทำลาย 'ความงาม' ของการเขียนโปรแกรมเชิงประกาศและทำให้วิศวกรบางคนค้นหาวิธีแก้ไขปัญหาอื่น ๆ การโยกย้ายของวิศวกรที่ไม่มีประสบการณ์จาก SQL เป็น NoSQL อาจถูกทริกเกอร์โดยความซับซ้อนพื้นฐานของฐานข้อมูลเชิงสัมพันธ์


2
"คลาส CSS เชิงลบไม่ได้เพิ่มเข้าไปในภาษาโดยเจตนาเนื่องจากปัญหาที่เกิดขึ้นกับ NP" - คุณช่วยอธิบายได้ไหม?
John Dvorak

มันเป็นแบบฝึกหัดเล็กน้อย แต่ด้วยตัวเลือก CSS เชิงลบคุณสามารถเขียนสิ่งเหล่านี้เป็นปัญหา 3SAT (ส่วนประโยคสุดท้ายเป็น DOM) ซึ่งจะต้องลองชุดค่าผสมที่เป็นไปได้ทั้งหมดเพื่อดูว่าตรงกันหรือไม่
Dibbeke

1
นอกจากนี้ขนาดเล็ก ใน CSS 3 และ 4 อนุญาตให้ใช้ตัวเลือกเชิงลบได้ แต่: ไม่สามารถใช้คลาส pseudo-class ได้
Dibbeke

2

เรามีความแตกต่างในการเสื่อมสภาพของภาษาการเขียนโปรแกรมที่ใช้งานได้ดีในการตรวจสอบตรรกะดิจิตอล

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

หนึ่งในภาษาที่ประกาศมากขึ้น / ส่วนย่อยภาษาที่เรียกว่าPSLสำหรับภาษาคุณสมบัติคุณสมบัติ เมื่อทำการทดสอบรูปแบบ RTL ของตัวคูณซึ่งตัวอย่างเช่นการดำเนินการทางตรรกะทั้งหมดของการเลื่อนและการเพิ่มผ่านวงจรนาฬิกาหลายรอบจะต้องมีการระบุ; assert that when enable is high, this output will equal the multiplication of these two inputs after no more than 8 clock cyclesคุณสามารถเขียนสถานที่ให้บริการในลักษณะของ คำอธิบาย PSL นั้นสามารถตรวจสอบได้พร้อมกับ RTL ในแบบจำลองหรือ PSL อาจได้รับการพิสูจน์อย่างเป็นทางการว่าจะเก็บไว้สำหรับคำอธิบาย RTL

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


1

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

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

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


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

1
@itsbruce สิ่งที่เป็นข้อมูลจริงส่วนใหญ่ไม่ได้ถูกแมปกับ ADT ได้อย่างง่ายดาย คิดว่าฐานข้อมูลส่วนใหญ่ทำงานอย่างไร ในฐานะ Prolog - Erlang คุณพูดถูกพวกมันเป็นภาษาที่ต่างกัน ฉันกล่าวว่าอันหนึ่งทำงานได้ในขณะที่อีกอันหนึ่งมีเหตุผล แต่ดีที่สุดถ้าฉันลบการเปรียบเทียบทั้งหมด
m3th0dman

1
@ m3th0dman ฐานข้อมูลเป็นเพียง tuples / บันทึกจำนวนมาก Haskell เป็นคนพิการเล็กน้อยที่นั่นเพราะมันไม่มีบันทึก แต่มันมีสิ่งอันดับและ ML มีทั้งคู่ และในกรณีของ Haskell จำนวนแผ่นเหล็กที่จำเป็นในการประกาศประเภทข้อมูลเรคคอร์ดหลอกใหม่ยังคงมีขนาดเล็กกว่าสิ่งที่ใช้ในการสร้าง faux-struct ในภาษา OOP แบบคงที่โดยเฉลี่ย คุณสามารถอธิบายรายละเอียดเกี่ยวกับวิธีที่ข้อมูลส่วนใหญ่ไม่ได้ถูกแมปกับ ADT ได้อย่างง่ายดายหรือไม่?
Doval

1
@ m3th0dman อานั่นเป็นเหตุผลที่ schema ฐานข้อมูลถูกกำหนดในภาษาที่จำเป็นซึ่งเหมาะสมกับงาน โอ้ไม่นั่นเป็น DDL ที่เปิดเผยได้ ในความเป็นจริงกระบวนการโดยรวมของการสร้างแบบจำลองข้อมูลมีความเกี่ยวข้องกับแอปพลิเคชันที่จะทำงานกับมันการไหลของข้อมูลและโครงสร้างไม่ใช่ภาษาที่ใช้งานแอปพลิเคชัน บางครั้งมีการบิดเบือนเพื่อให้ตรงกับคุณสมบัติ OO ของภาษาและสิ่งที่ออมของมันรองรับ แต่มักจะเป็นสิ่งที่ไม่ดีไม่ใช่คุณสมบัติ ภาษาที่มีการประกาศเหมาะสมกว่าการแสดงโมเดลข้อมูลเชิงแนวคิด / ตรรกะ
itsbruce

1
@itsbruce ฉันไม่ได้บอกว่ากระบวนทัศน์กระบวนทัศน์นั้นดีกว่าการประกาศที่กำหนดข้อมูล; ฉันกำลังบอกว่ากระบวนทัศน์ที่เปิดเผยไม่ได้ดีกว่าหรือแย่กว่ากระบวนวิธีหนึ่ง (สำหรับภาษาที่ใช้โดยทั่วไป) สำหรับการจัดการข้อมูลส่วนที่เปิดเผยของ SQL นั้นไม่เพียงพอสำหรับการใช้งานจริง มิฉะนั้นจะไม่มีใครคิดค้นและใช้ส่วนขยายขั้นตอน สำหรับบทความที่ฉันไม่เห็นด้วยกับมันจากนามธรรมที่ขัดแย้งกับบรูคส์; เขาสร้างความคิดของเขาจากโครงการจริงในขณะที่คนเหล่านั้นไม่ได้สร้างสิ่งที่โดดเด่นเพื่อพิสูจน์ทฤษฎีของพวกเขา
m3th0dman

0

มันจะมีลักษณะเช่นนี้ .. {(อะไรก็ตาม => อ่านไฟล์และเรียก url) | เรียก url & read a file} อย่างไรก็ตามสิ่งเหล่านี้เป็นการกระทำที่จะดำเนินการและสถานะของระบบจะเปลี่ยนไปตามผลลัพธ์ แต่ไม่ชัดเจนจากแหล่งที่มา

Declaratives สามารถอธิบายเครื่องจักรสถานะ จำกัด และช่วงการเปลี่ยนภาพ FSM นั้นตรงกันข้ามกับสิ่งที่ประกาศโดยไม่มีการกระทำแม้ว่าการกระทำเพียงอย่างเดียวคือการเปลี่ยนสถานะเป็นสถานะถัดไป

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

ฉันรู้ว่ามันฟังดูแปลก ๆ แต่ในปี 2008 ฉันเขียนตัวสร้างโปรแกรมที่ใช้วิธีนี้และ C ++ ที่สร้างขึ้นมานั้นมีค่าตั้งแต่ 2 ถึง 15 เท่าของที่มา ตอนนี้ฉันมี C ++ มากกว่า 75,000 บรรทัดจากอินพุต 20,000 บรรทัด สองสิ่งนี้: ความสอดคล้องและความสมบูรณ์

ความสอดคล้อง: ไม่มีเพรดิเคตสองตัวที่สามารถเป็นจริงได้ในเวลาเดียวกันสามารถบ่งบอกถึงการกระทำที่ไม่สอดคล้องกันเนื่องจากทั้ง x = 8 และ x = 9 หรือสถานะถัดไปที่แตกต่างกัน

ความสมบูรณ์: ระบุตรรกะสำหรับการเปลี่ยนสถานะทุกครั้ง สิ่งเหล่านี้อาจเป็นเรื่องยากที่จะตรวจสอบระบบที่มีสถานะย่อย N กับ> 2 ** N ฯ แต่มีวิธี combinatorial ที่น่าสนใจที่สามารถตรวจสอบทุกอย่างได้ ในปี 1962 ฉันเขียนเฟสที่ 1 ของการเรียงลำดับระบบสำหรับเครื่อง 7070 โดยใช้การสร้างรหัสตามเงื่อนไขแบบนี้และดีบัก combinatorial จาก 8,000 บรรทัดในการเรียงลำดับจำนวนข้อบกพร่องจากวันที่ปล่อยครั้งแรกตลอดไปเป็นศูนย์!

ระยะที่สองของการเรียงลำดับ 12,000 บรรทัดมีข้อผิดพลาดมากกว่า 60 ข้อในช่วงสองเดือนแรก ยังมีอีกมากที่จะพูดเกี่ยวกับเรื่องนี้ แต่มันใช้งานได้ หากผู้ผลิตรถยนต์ใช้วิธีนี้เพื่อตรวจสอบเฟิร์มแวร์เราจะไม่เห็นความล้มเหลวที่เราเห็นในตอนนี้


1
สิ่งนี้ไม่ได้ตอบคำถามเดิม ปัจจัยความมั่นคงและความครบถ้วนสมบูรณ์ทำอย่างไรกับความจริงที่ว่าการเขียนโปรแกรมส่วนใหญ่ยังคงเป็นขั้นตอนไม่ใช่การประกาศ?
Jay Elston

ย่อหน้าเปิดของคุณดูเหมือนจะเป็นคำตอบสำหรับโปรแกรมเมอร์ในคำตอบของ arnaud.stackexchange.com/a/275839/67057 ไม่ใช่คำถาม มันควรจะเป็นความคิดเห็นที่นั่น (บนหน้าจอของฉันคำตอบของคุณจะไม่ต่ำกว่าเขาอีกแล้วสำหรับสิ่งหนึ่ง) ฉันคิดว่าส่วนที่เหลือของคำตอบของคุณเป็นตัวอย่างของวิธีการที่รหัสประกาศจำนวนเล็กน้อยสามารถสร้างรหัสคำสั่งที่เทียบเท่าได้จำนวนมาก แต่ไม่ชัดเจน คำตอบของคุณต้องมีการจัดระเบียบโดยเฉพาะอย่างยิ่งในประเด็นสำคัญ
itsbruce

-3

ไม่ใช่ทุกสิ่งที่จะแสดงด้วยวิธีการเปิดเผย

บ่อยครั้งที่คุณต้องการควบคุมการไหลของการดำเนินการอย่างชัดเจน

ตัวอย่างต่อไปนี้หลอกรหัส: if whatever read a file call an URL else call an URL write a file คุณจะเป็นตัวแทนได้อย่างไร?

แน่นอนว่าอาจมีวิธีแปลกใหม่ที่จะทำ เช่นเดียวกับmonads แต่สิ่งเหล่านี้มักจะยุ่งยากซับซ้อนและน้อยกว่าสัญชาตญาณ

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

Declarative นั้นยอดเยี่ยมสำหรับทุกสิ่งที่เกี่ยวข้องกับการคำนวณอย่างแท้จริง เช่นเดียวกับฟังก์ชั่นยักษ์คุณใส่ X เข้ากับคุณได้ Y นั่นเยี่ยมมาก ตัวอย่างสำหรับสิ่งนี้คือ HTML อินพุตคือข้อความเอาต์พุตคือสิ่งที่คุณเห็นในเบราว์เซอร์ของคุณ


2
ฉันไม่ซื้อสิ่งนี้ ทำไมตัวอย่างของคุณจึงไม่เปิดเผย มันเป็นif/ else, ในกรณีใดสิ่งที่ทางเลือกที่เปิดเผยจะมีลักษณะอย่างไร แน่นอนว่าไม่ใช่read/ write/ callชิ้นส่วนเนื่องจากเป็นรายการค่าที่ดี (ถ้าคุณหมายถึงว่าห่อไว้{...; ...}แล้วทำไมไม่ห่อหุ้มด้วย[..., ...]ล่ะ?) แน่นอนว่ารายการนั้นเป็นรายการฟรี คนอื่น ๆ ก็ทำเช่นกัน ฉันไม่เห็นว่าทำไม monads จึงเกี่ยวข้องที่นี่ พวกเขาเป็นเพียง API Haskell เดินจากลำธาร -> monads เพื่อช่วยจัดองค์ประกอบเอง แต่ภาษาลอจิกสามารถเขียนรายการตามลำดับโดยอัตโนมัติ
Warbo

2
-1 สำหรับ Monads เพียงอย่างเดียว 1. พวกเขาไม่ได้แปลกใหม่ (รายการและชุดเป็น Monads และทุกคนใช้มัน) 2 พวกเขาไม่มีอะไรจะทำอย่างไรกับการบังคับให้สิ่งที่จะต้องทำในลำดับที่เฉพาะเจาะจง (Haskell ไม่โน้ตรูปลักษณ์ความจำเป็น แต่ไม่ได้) ภาษาสำหรับการประกาศ / การทำงานระบุความสัมพันธ์และการพึ่งพา ถ้าฟังก์ชัน X ต้องการอินพุต Y, Y จะถูกสร้างขึ้นก่อนที่ X รับการขึ้นต่อกันที่ถูกต้องและลำดับเหตุการณ์ที่เหมาะสมจะกำหนดตัวเอง การทำงานร่วมกันหลายอย่างเกิดจากเหตุการณ์ไม่ใช่ในลำดับเดียว ภาษาที่ประกาศไม่ได้ทำให้การตอบสนองต่อเหตุการณ์ยากขึ้น
itsbruce

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

1
นอกเหนือจาก @itsbruce ตัวอย่างการเขียนโปรแกรมแบบใช้ปฏิกิริยายังพิจารณาถึงการประกาศและเกี่ยวข้องกับการโต้ตอบกับสภาพแวดล้อม
Maciej Piechotka
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.