เหตุใดภาษาการเขียนโปรแกรมบางภาษาจึงทัวริงสมบูรณ์ แต่ขาดความสามารถบางอย่างของภาษาอื่น


42

ฉันพบปัญหาแปลก ๆ เมื่อเขียนล่ามที่ (ควร) hooks ไปยังโปรแกรม / ฟังก์ชั่นภายนอก: ฟังก์ชั่นใน 'C' และ 'C ++' ไม่สามารถขอฟังก์ชั่นแปรผันได้เช่นฉันไม่สามารถสร้างฟังก์ชั่นที่เรียกว่า 'printf' ด้วยอาร์กิวเมนต์เดียวกันที่แน่นอนที่ได้รับและแทนที่จะต้องเรียกใช้เวอร์ชันอื่นที่ใช้วัตถุแปรปรวน นี่เป็นปัญหาอย่างมากเนื่องจากฉันต้องการสร้างวัตถุที่มีตะขอที่ไม่ระบุชื่อ

ดังนั้นฉันคิดว่านี่แปลกตั้งแต่Forth , JavaScriptและบางทีภาษาอื่น ๆ สามารถทำได้อย่างง่ายดายโดยไม่ต้องหันไปใช้ภาษาแอสเซมบลี / รหัสเครื่อง เนื่องจากภาษาอื่นสามารถทำสิ่งนี้ได้อย่างง่ายดายนั่นหมายความว่าระดับของปัญหาที่แต่ละภาษาโปรแกรมสามารถแก้ไขได้แตกต่างกันไปตามภาษาแม้ว่าภาษาเหล่านี้จะทัวริงสมบูรณ์หรือไม่


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

8
ดูสิ่งที่เครื่องจักรทัวริงทำและคุณจะเห็นว่า "ทัวริงสมบูรณ์" เป็นเครื่องกีดขวางที่ต่ำมากในการล้าง โดยพื้นฐานสิ่งใดก็ตามที่สามารถ 'อ่าน', 'เขียน' และ 'กระโดด' ในขณะที่สนับสนุนการคำนวณทางคณิตศาสตร์ขั้นพื้นฐานคือทัวริงสมบูรณ์ นั่นต่ำกว่าระดับของคุณสมบัติภาษาที่คุณกำลังดูอยู่
59

2
จะไร้สาระยิ่งขึ้น: คำสั่ง MOV ในโปรเซสเซอร์ x86 นั้นเป็นการทัวริงสมบูรณ์ ดูcl.cam.ac.uk/~sd601/papers/mov.pdfสำหรับรายละเอียด
Gareth McCaughan

3
แม้แต่เวทย์มนตร์ของเกม: The Gathering ก็ยังสมบูรณ์แบบอยู่ ทัวริงสมบูรณ์ไม่มีอะไรเกี่ยวข้องกับคุณสมบัติของภาษา
เสา

2
BTW ยังมีภาษาการเขียนโปรแกรมที่ซับซ้อนมากซึ่งไม่ได้ทำให้สมบูรณ์เช่นตัวตรวจสอบหลักฐาน
盛安安

คำตอบ:


68

NkN

λ

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

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

ทัวริงที่สมบูรณ์และการแสดงออกทางภาษาเป็นสองความคิดที่แตกต่างกัน


42
Edwin Brady ผู้ออกแบบของ Idris (เพียงครึ่งเดียว) ใช้เรื่องตลก (ฉันไม่รู้ว่าเขาประดิษฐ์หรือไม่) คำว่า "Tetris-complete" เพื่อแสดงความแตกต่างระหว่าง "สามารถคำนวณฟังก์ชันใด ๆ ที่คำนวณได้บนตัวเลขธรรมชาติ" และ "สามารถ ถูกใช้เพื่อเขียนโปรแกรมที่ไม่น่าสนใจซึ่งมีปฏิสัมพันธ์กับสิ่งแวดล้อม "
Jörg W Mittag

12
คุณอาจพูดถึงว่าคุณสามารถมีสิ่งเหล่านั้นใน C / C ++ คุณเพียงแค่ต้องเขียนโค้ดบางอย่างที่ทำหน้าที่เป็นคอมไพเลอร์ใน C / C ++ สำหรับภาษาอื่นที่มีพวกเขาที่โค้ดของคุณรวบรวมสตริงในรหัส C / C ++ ของคุณ จากนั้นคุณสามารถเขียนโปรแกรมในรูปแบบอย่าง Java ภายในไฟล์ C ของคุณ ทั้งหมดนี้จะเป็นงานจำนวนมาก แต่เป็นไปได้ (พิสูจน์ได้ว่าเพราะ C / C ++ คือ Turing Complete)
Shufflepants

4
@Shufflepants ฉันสงสัยว่ามันจะมีประโยชน์จริง ๆ ถ้าพูดว่า "ฉันสามารถทำได้ใน C ++ เพราะฉันสามารถแปลภาษาอื่นได้" โดยโทเค็นนั้น Java, ML, C ++ จะเทียบเท่า TM ที่มี oracle สำหรับ syscalls (I / O) ก็มีค่าเทียบเท่า ฉันกลัวว่าด้วยเหตุผลนั้นแทบทุกภาษามีความหมายเท่า ๆ กัน ถ้าเป็นเช่นนั้นมันไม่ใช่ความคิดที่เป็นประโยชน์ในการเปรียบเทียบภาษา
Chi

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

5
@Rhymoid หาก C ไม่ทัวริงเสร็จสมบูรณ์ด้วยเหตุผลในการเข้าถึงหน่วยความจำหรือเพราะสามารถส่งสัญญาณโดยพลการไปยังอุปกรณ์ที่เชื่อมต่อซึ่งมีที่เก็บข้อมูลขนาดใหญ่โดยพลการไม่นับ . แต่ฉันไม่รู้สึกว่าเป็นเหตุผลที่ให้ผลดีมาก
Shufflepants

47

ทัวริงสมบูรณ์เป็นแนวคิดนามธรรมของการคำนวณ หากภาษาทัวริงสมบูรณ์แล้วก็มีความสามารถในการคำนวณใด ๆ ที่ภาษาทัวริงสมบูรณ์อื่น ๆ สามารถทำได้

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

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

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


1
@ Wildcard ฉันจะเห็นว่าคอมไพเลอร์ทุกคนเป็น wrt ที่ไม่ปลอดภัยนี้ ภาษาส่วนใหญ่มีความสมบูรณ์แบบทัวริง แต่ในที่สุดก็จำเป็นต้องตีความโดย / รวบรวมเป็นชุดประกอบซึ่งไม่ได้ แต่นี่เป็นข้อ จำกัด ทางกายภาพที่จำเป็น - ฮาร์ดแวร์ไม่มีวันทัวริงที่มีประสิทธิภาพ อย่างไรก็ตามความสามารถในการคำนวณมีแนวคิดที่มีประโยชน์มากมายซึ่ง "นำไปใช้" ในทางปฏิบัติสำหรับคอมพิวเตอร์ในโลกแห่งความจริง
Chi

3
@ Wildcard ในความหมายเล็กน้อย Assembly (และ C) มีพอยน์เตอร์ขนาดคงที่ซึ่งสามารถระบุจำนวนหน่วยความจำที่มีขอบเขตได้เท่านั้น ตามหลักการแล้วเราสามารถกำหนดแอสเซมบลีที่ซึ่งพอยน์เตอร์เป็นธรรมชาติไม่ได้ จำกัด แต่ฉันจะไม่เรียกว่า "แอสเซมบลี" อีกต่อไป - ฉันจะเรียกว่า URM หรืออะไรทำนองนั้น ในทางปฏิบัติเราเพียงแค่เสแสร้งขอบเขตทางกายภาพนั้นมีขนาดใหญ่พอที่จะอนุญาตให้โปรแกรมของเราทำงานดังนั้นแม้ว่าคอมพิวเตอร์เป็นเพียงเครื่องสถานะ จำกัด (หมายความว่าไม่สามารถทำได้เช่นทำการเพิ่ม) เราคิดว่ามันเป็นเครื่องทัวริง ดังนั้นการเพิ่มจึงทำได้)
Chi

4
@chi นั่นไม่ถูกต้องนัก ก่อนอื่นแทบทุกคนคิดว่า C กำลังจะทำให้ทัวริงสมบูรณ์เพราะโดยทั่วไปเรามักจะใช้ถ้อยคำรอบ ๆ สมมติฐานที่ว่า "คุณมีความจำเพียงพอ" สำหรับผู้ที่มีจำนวนน้อยมากที่ต้องกังวลเกี่ยวกับถ้อยคำที่เข้มงวดมากขึ้นซึ่งสมมติฐานดังกล่าวไม่ถูกต้อง C ไม่ได้ระบุขนาดของตัวชี้และไม่ได้ระบุขอบเขตของจำนวนหน่วยความจำที่สามารถแก้ไขได้ ดังนั้นแม้ในความหมายที่เข้มงวดที่สุดของ "ทัวริงสมบูรณ์" C ก็เป็นทัวริงสมบูรณ์
Cort Ammon

3
@CortAmmon ฉันต้องไม่เห็นด้วย หากเราทำให้ความหมายของ C เป็นแบบเป็นทางการพยายามที่จะฝังสมมติฐาน "หน่วยความจำเพียงพอ" เราจะล้มเหลวเนื่องจากsizeof(void *)ได้รับคำสั่งให้ประเมินบางสิ่งตามมาตรฐาน ISO C สิ่งนี้บังคับให้เราต้อง จำกัด จำนวนหน่วยความจำสำหรับโปรแกรมที่กำหนดให้กับบางสิ่งที่มีขนาดใหญ่ - แต่ยังคงมีขอบเขต เช่นฉันไม่สามารถเขียนโปรแกรมที่มีความหมายเพิ่มสองธรรมชาติโดยพลการ C อาจยังคงทำให้ทัวริงมีประสิทธิภาพผ่าน I / O โดยใช้ไฟล์เช่น TM tapes (ตาม @Hurkyl ชี้ไปที่ด้านบน) ฉันเห็นด้วยกับสิ่งนี้ว่าไม่ใช่ประเด็นปัญหาในทางปฏิบัติ
Chi

7
ฉันขอแนะนำภาษาใหม่ C-inf ซึ่งเหมือนกับ C ยกเว้นเมื่อมีการจัดสรรหน่วยความจำมากเกินไปผ่านการเรียกซ้ำหรือการจัดสรรฮีปโปรแกรมจะถูกยกเลิกยกเลิกคอมไพล์ใหม่ด้วยค่าขนาดใหญ่กว่า (void *) และ sizeof (size_t) และเริ่มทำงานอีกครั้งตั้งแต่เริ่มต้น
gnasher729

26

นึกถึงภาษาการเขียนโปรแกรมเป็นยานพาหนะทางบกที่แตกต่างกัน: จักรยาน, รถยนต์, โฮเวอร์คาร์, รถไฟ

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

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


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

2
เร็วกว่าการเดินทางด้วยแสงน่าจะเป็นการเปรียบเทียบที่ดีกว่าสำหรับการคำนวณแบบ Super-Turing มันอาจจะเป็นไปได้ แต่คนส่วนใหญ่คิดว่ามันไม่
jmite

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

1
@ Luaan ใช่แล้ว แต่สมองของเราไม่จำเป็นต้องเป็นซุปเปอร์ทัวริงในการทำความเข้าใจกับคอมพิวเตอร์ทัวริง ฉันสามารถอธิบายความหมายของทัวริงเครื่องจักรโดยใช้ภาษาที่สิ้นสุดที่อ่อนแอกว่าเช่น Simply Typed แลมบ์ดาแคลคูลัสโดยการเขียนฟังก์ชั่นที่ใช้ TM และสถานะของมันและก้าวไปสู่สถานะถัดไป จริง ๆ แล้วฉันไม่สามารถเรียกใช้เครื่องในภาษานั้น (เพราะอาจใช้ขั้นตอนที่ไม่มีที่สิ้นสุด) แต่ฉันสามารถเขียนได้ว่าแต่ละขั้นตอนมีลักษณะอย่างไร
jmite

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

17

สิ่งที่คุณถามเป็นหลักคือความแตกต่างระหว่างพลังการคำนวณและสิ่งที่เรียกว่าพลังการแสดงออก (หรือเพียงแค่การแสดงออก ) ของภาษา (หรือระบบการคำนวณ)

พลังการคำนวณ

กำลังการคำนวณหมายถึงสิ่งที่ชนิดของปัญหาภาษาที่สามารถคำนวณ ชั้นที่รู้จักมากที่สุดของการใช้พลังงานในการคำนวณคือสิ่งที่เทียบเท่ากับทัวริงเครื่องสากล มีระบบการคำนวณอื่น ๆ มากมายเช่นRandom Access Machines , calcul-แคลคูลัส , แคลคูลัสSK combinator , ฟังก์ชัน rec-recursive , WHILEโปรแกรมและอื่น ๆ อีกมากมาย และเมื่อปรากฎว่าสิ่งเหล่านี้สามารถจำลองซึ่งกันและกันซึ่งหมายความว่าพวกเขาทั้งหมดมีพลังการคำนวณเหมือนกัน

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

  1. ระบบคอมพิวเตอร์ทั้งหมดที่มีความสามารถในการคำนวณทั่วไปมีประสิทธิภาพเท่าเทียมกันและ
  2. มนุษย์ที่ติดตามอัลกอริทึมสามารถคำนวณฟังก์ชั่นได้อย่างแม่นยำที่ทัวริงเครื่องจักร (และระบบอื่น ๆ ) สามารถคำนวณได้

ที่สองมีความสำคัญในสาขาปรัชญาของจิตใจมากกว่าวิทยาศาสตร์คอมพิวเตอร์

อย่างไรก็ตามมีสองสิ่งที่คริสตจักรทัวริง - วิทยานิพนธ์ไม่ได้พูดซึ่งเกี่ยวข้องกับคำถามของคุณ:

  1. การจำลองสถานการณ์ต่าง ๆ นั้นมีประสิทธิภาพเพียงใดและ
  2. วิธีที่สะดวกในการเข้ารหัสของปัญหาคือ

ตัวอย่างง่าย ๆ สำหรับ (1): บน Random Access Machine การคัดลอกอาร์เรย์จะใช้เวลาตามสัดส่วนกับความยาวของอาร์เรย์ บนเครื่องทัวริง แต่มันต้องใช้สัดส่วนเวลากลับไปตารางของความยาวของอาร์เรย์เพราะเครื่องทัวริงไม่ได้มีการเข้าถึงหน่วยความจำแบบสุ่มก็สามารถย้ายข้ามเทปเซลล์หนึ่งในช่วงเวลาที่ ดังนั้นจึงจำเป็นต้องย้ายองค์ประกอบnของอาร์เรย์nครั้งเพื่อคัดลอก ดังนั้นรูปแบบการคำนวณที่แตกต่างกันอาจมีลักษณะการทำงานที่แตกต่างกันแม้ในกรณี asymptotic ที่เราพยายามสรุปจากรายละเอียดการใช้งาน

ตัวอย่างสำหรับ (2) มากมาย: ทั้ง calcul-แคลคูลัสและPythonเป็นทัวริงสมบูรณ์ แต่คุณอยากจะเขียนโปรแกรมใน Python หรือ calcul-แคลคูลัสมากกว่าไหม

นอกจากนี้ยังมีรอยย่นที่สามที่ฉันมีรอบจนกระทั่งตอนนี้: ระบบดั้งเดิมเหล่านั้นทั้งหมดได้รับการออกแบบโดยนักตรรกวิทยานักปรัชญาหรือนักคณิตศาสตร์ไม่ใช่นักวิทยาศาสตร์คอมพิวเตอร์ ... เพียงเพราะคอมพิวเตอร์และวิทยาศาสตร์คอมพิวเตอร์ไม่ได้อยู่ เหล่านี้ไปทั้งหมดกลับไปยังต้น 1930S แม้กระทั่งก่อนที่Konrad Zuse 's มากทดลองครั้งแรก (ซึ่งไม่ได้ตั้งโปรแกรมและ / หรืออยู่แล้วทัวริงสมบูรณ์) พวกเขาพูดถึง "ฟังก์ชั่นคำนวณตัวเลขธรรมชาติเท่านั้น"

ตอนนี้กลายเป็นว่ามีหลายสิ่งที่คุณสามารถแสดงเป็นฟังก์ชั่นกับตัวเลขธรรมชาติ - หลังจากทั้งหมดคอมพิวเตอร์ที่ทันสมัยของเราได้รับโดยที่น้อยกว่ามาก (โดยทั่วไป 3-4 ฟังก์ชั่นของตัวเลข 0 และ 1 และนั่นคือ ) แต่ตัวอย่างเช่นระบบปฏิบัติการคำนวณอะไรได้บ้าง?

ความคิดของ I / O, ผลข้างเคียง, การโต้ตอบกับสภาพแวดล้อมไม่ได้ถูกรวบรวมโดยแนวคิดของ "ฟังก์ชันเหนือจำนวนธรรมชาติ" และมันก็เป็นสิ่งที่สำคัญเนื่องจากSimon Peyton Jonesเคยกล่าวไว้ว่า"ฟังก์ชั่นล้วนๆที่ไม่มีผลข้างเคียงใด ๆ เลยก็คือทำให้ซีพียูของคุณร้อนแรง"ซึ่งสมาชิกผู้ฟังตอบ"จริง ๆ แล้วมันคือด้าน - ผลเช่นกัน! "

Edwin Bradyผู้ออกแบบของIdris (เพียงครึ่งเดียว) ใช้เรื่องตลก (ฉันไม่รู้ว่าเขาประดิษฐ์หรือไม่) คำว่า "Tetris-complete" เพื่อแสดงความแตกต่างระหว่าง "สามารถคำนวณฟังก์ชันใด ๆ ที่คำนวณได้บนตัวเลขธรรมชาติ" และ "สามารถ ถูกใช้เพื่อเขียนโปรแกรมที่ไม่น่าสนใจซึ่งมีปฏิสัมพันธ์กับสิ่งแวดล้อม " เขาแสดงให้เห็นถึงสิ่งนี้มากขึ้นโดยการติดตั้งSpace Invaders ที่โคลนใน Idrisแต่เขาบอกว่าเขามั่นใจว่า Tetris จะลดการบุกรุกของ Space

สิ่งที่จะชี้ให้เห็นก็คือว่าไม่เพียง แต่เป็นทัวริง-เท่าเทียมกันไม่จำเป็นต้องมากพอที่จะพูดคุยเกี่ยวกับการเขียนโปรแกรมจริง "ประโยชน์" มันอาจ OTOH ยังไม่ได้necesssary เช่นSQL กลายเป็นทัวริงเทียบเท่ากับ ANSI SQL: 1999แต่ก็ยังมีประโยชน์ก่อนหน้านั้น ในความเป็นจริงบางคนอาจโต้แย้งว่าการทำให้ทัวริงเทียบเท่าไม่ได้เพิ่มประโยชน์ใด ๆ เลย มีภาษาเฉพาะโดเมนจำนวนมากที่ไม่เทียบเท่าทัวริง ข้อมูลคำอธิบายภาษามักจะไม่ได้ (และไม่ควร) ภาษาโดยรวมนั้นไม่สามารถเทียบเท่าทัวริงได้ แต่คุณยังสามารถเขียนลูปเหตุการณ์เว็บเซิร์ฟเวอร์หรือระบบปฏิบัติการในภาษาเหล่านั้นได้ นอกจากนี้ยังมีภาษาที่เทียบเท่ากับทัวริง แต่นี่ถือว่าเป็นความผิดพลาดจริง ๆ

ดังนั้นโดยสรุปทัวริงนั้นไม่น่าสนใจอย่างมากเว้นแต่คุณต้องการวิเคราะห์โปรแกรมแบบคงที่

ลึกซึ้ง

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

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

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

สัญชาตญาณหลักคือ: เมื่อแปลโปรแกรมจากภาษาเป็นภาษาอื่นการเปลี่ยนแปลงบางอย่างที่คุณต้องทำมีอยู่ในตัวเครื่อง (เช่นเช่นการเปลี่ยนFORลูปเป็นWHILEลูปหรือลูปเป็นเงื่อนไขGOTO) และบางคนต้องการการเปลี่ยนแปลงทั่วโลก โครงสร้างของโปรแกรม

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

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

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

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

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

ตัวอย่างที่ฉันพบในแท็ก Ruby บน StackOverflow: ผู้ใช้หลายคนที่ทำตามแท็ก Ruby อ้างว่าลูปง่ายต่อการเข้าใจมากกว่าการเรียกซ้ำและการเรียกซ้ำเป็นเพียงสำหรับโปรแกรมเมอร์ขั้นสูงและลูปเท่านั้นที่เข้าใจง่ายสำหรับผู้ใช้ใหม่ ผู้มาใหม่ที่สมบูรณ์ซึ่งเขียนโค้ดแบบนี้โดยสังหรณ์ใจ:

def rock_paper_scissors
  get_user_input
  determine_outcome
  print_winner
  rock_paper_scissors # start from the top
end

ซึ่งมักจะนำไปสู่หลาย ๆ คนที่แสดงความคิดเห็นว่า "สิ่งนี้ไม่ได้ผล" และ "พวกเขาทำผิด" และ "วิธีที่ถูกต้อง" คือ:

def rock_paper_scissors
  loop do
    get_user_input
    determine_outcome
    print_winner
  end
end

เห็นได้ชัดว่ามีบางคนที่การเรียกซ้ำหางเป็นวิธีที่เป็นธรรมชาติมากขึ้นในการแสดงแนวคิดของ "การวนซ้ำ" มากกว่าการสร้างแบบวนซ้ำ

สรุป

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

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

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

ใช่.

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

7

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

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

สิ่งเหล่านี้อาจเป็นที่สนใจ:


5

ภาษาทัวริงที่สมบูรณ์สามารถคำนวณสิ่งเดียวกันได้

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

นี่คือตัวอย่างบางส่วน:

  • หากคุณไม่มี enums คุณสามารถใช้จำนวนเต็ม
  • หากคุณไม่มีบัฟเฟอร์ที่รู้ขนาดของมันคุณสามารถสร้างประเภทที่มีขนาดและบัฟเฟอร์ที่ไม่ทราบขนาดได้
  • หากคุณไม่มีการตรวจสอบขอบเขตของบัฟเฟอร์คุณสามารถตรวจสอบดัชนีทุกครั้งที่คุณใช้งาน
  • หากคุณไม่มีฟังก์ชัน Variadic คุณสามารถสร้างฟังก์ชั่นที่รับบัฟเฟอร์ที่รู้ขนาดและอ่านจากบัฟเฟอร์นั้นเป็นข้อมูลเดียวกับที่คุณได้รับจากอาร์กิวเมนต์ที่เป็นทางการ
  • หากคุณไม่มีโอเปอเรเตอร์คุณสามารถใช้ฟังก์ชั่น
  • หากคุณไม่มีประเภทที่สามารถสืบทอดซึ่งกันและกันคุณสามารถสร้างประเภทที่มีซึ่งกันและกันและเข้าถึงพวกเขาผ่านทางอ้อมในระดับพิเศษโดยมีการพิมพ์ย่อยเป็นเพียงการเปลี่ยนรูปแบบของ จัดการ-to-บรรจุชนิด
  • หากคุณไม่มีผู้รับมอบสิทธิ์ แต่คุณมีพอยน์เตอร์ของฟังก์ชันคุณสามารถสร้างประเภทที่มีออบเจ็กต์อ้างอิงและตัวชี้ฟังก์ชัน
  • หากคุณไม่มีตัวแทน แต่คุณมีอินเทอร์เฟซคุณสามารถประกาศอินเทอร์เฟซที่ประกอบด้วยวิธีการเดียวที่มีลายเซ็นที่คุณต้องการ
  • หากคุณไม่มีประเภททั่วไปคุณสามารถใช้ประเภทที่ไม่ใช่ประเภททั่วไปซึ่งจะถือว่าเฉพาะขอบเขตบนหรือล่างที่คุณสนใจเท่านั้น (และอาจใช้ cast ที่เหมาะสมที่จุดใช้งานเพื่อให้คอมไพเลอร์มีความสุข)
  • หากคุณไม่มีระบบการพิมพ์แบบเชิงเส้น / เลียนแบบคุณสามารถหลีกเลี่ยงการใช้ตัวแปรใด ๆ ได้มากกว่าหนึ่งครั้ง
  • ... และต่อไป

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

สิ่งที่คำนวณได้ล้วนถูกตอกย้ำมาเป็นเวลานานแล้ว


4

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

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


2

ด้านบนของคำตอบของคนอื่นนี่คือการเปรียบเทียบอีก

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

ดังนั้นความแตกต่างระหว่างเครื่องซักผ้าแบบคอมพิวเตอร์ที่ทันสมัยกับหินข้างแม่น้ำคืออะไร?

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

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


2

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

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

ตอนนี้ให้พิจารณา sublanguage ของเครื่องจักรทัวริงทั้งหมดที่อ่านและเขียนเฉพาะอักขระ a, b และ blank เป็นทัวริงที่สมบูรณ์ แต่ไม่สามารถแสดงโปรแกรมใด ๆ ที่สร้าง c บนอินพุตทั้งหมดเนื่องจากไม่สามารถเขียน cs ใด ๆ มันสามารถแสดงฟังก์ชั่นที่คำนวณได้ทั้งหมดในอินพุตและเอาต์พุตที่เข้ารหัสเป็นสตริงของ as และ bs เท่านั้น

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

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