ภาษาการเขียนโปรแกรมที่จำเป็นไม่รองรับการเรียกซ้ำ?


21

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

ภาษาใดที่ไม่รองรับการสอบถามซ้ำตั้งแต่เริ่มต้นและการสนับสนุนนั้นเพิ่มเมื่อใด

คำตอบ:


21

ฉันไม่แน่ใจว่า COBOL ทำ (แน่นอนไม่ได้ในคราวเดียว) แต่ฉันไม่สามารถจินตนาการได้เลยว่าใครจะห่วงใยมากเกินไป

Fortran มีมาตั้งแต่ Fortran 90 แต่ต้องการให้คุณใช้recursiveคำหลักเพื่อบอกว่ารูทีนย่อยซ้ำ

PL / ฉันค่อนข้างเหมือนกัน - รองรับการเรียกซ้ำ แต่คุณต้องบอกอย่างชัดเจนว่ากระบวนการใดที่เรียกซ้ำ

ฉันสงสัยว่ามีมากกว่านั้น เมื่อคุณลงไปห้ามการเรียกซ้ำเป็นส่วนใหญ่สิ่งที่ IBM ทำในการออกแบบภาษาของพวกเขาด้วยเหตุผลง่าย ๆ ที่เมนเฟรมของ IBM (360/370/3090 / ... ) ไม่สนับสนุนสแต็กในฮาร์ดแวร์ เมื่อภาษาส่วนใหญ่มาจาก IBM พวกเขาส่วนใหญ่ห้ามการเรียกซ้ำ ตอนนี้พวกเขามาจากที่อื่น ๆ แล้วอนุญาตให้เรียกซ้ำได้เสมอ (แม้ว่าฉันควรจะเพิ่มเครื่องอื่น ๆ อีกสองสามเครื่องโดยเฉพาะ Cray 1 ดั้งเดิมโดยไม่มีฮาร์ดแวร์รองรับสแต็ก)


คอมพิวเตอร์ควบคุมข้อมูลของช่วงเวลานั้นไม่รองรับการเรียกซ้ำ (การเรียกรูทีนย่อยถูกทำด้วยคำสั่งที่แก้ไขโค้ดเพื่อแทรกการข้ามไปยังคำสั่งการโทร + 1) เมื่อเวิร์ ธ พัฒนาปาสคาลใน 6600 เขาคงจะต้องคิดหาวิธีการใหม่ในการเรียกรูทีนย่อย
David Thornley

@ David: ใช่ - และไม่ใช่เรื่องบังเอิญพวกเขาออกแบบโดย Seymour Cray ฉันเคยดูคอมไพเลอร์ Pascal 6000 แต่จำไม่ได้ว่ามองสิ่งที่มันทำเพื่อสร้าง (จำลอง?) สแต็กเฟรม
Jerry Coffin

notably the original cray 1ดังนั้นคุณไม่จำเป็นต้องเรียกซ้ำตัวเองเพื่อโคลนไดโนเสาร์? ฉันเดาว่ามันขึ้นอยู่กับเราแล้วที่ลิงจะแกว่งผ่านต้นไม้
normanthesquid

2
แม้ CAML (และ OCAML, F #) จำเป็นต้องมีฟังก์ชั่นวนซ้ำอย่างชัดเจน
jk

1
@Panercrisis: ฉันไม่แน่ใจว่า IBM มีส่วนเกี่ยวข้องกับ x86 หรือไม่ แต่เมนเฟรมปัจจุบันของพวกเขาติดตามกลับไปที่ IBM 360 โดยตรงซึ่งเปิดตัวในปี 1964 ดังนั้นการออกแบบพื้นฐานจึงมาถึง x86 ภายในสองสามทศวรรษหรือมากกว่านั้น
Jerry Coffin

16

Wikipedia พูดว่า:

ภาษายุคแรก ๆ เช่น Fortran ไม่สนับสนุนการเรียกซ้ำเนื่องจากการจัดสรรตัวแปรแบบคงที่เช่นเดียวกับที่ตั้งสำหรับที่อยู่ผู้ส่ง

http://en.wikipedia.org/wiki/Subroutine#Local_variables.2C_recursion_and_re-entrancy

FORTRAN 77 ไม่อนุญาตการเรียกซ้ำ, Fortran 90 ทำ, (กิจวัตรที่เรียกซ้ำจะต้องประกาศอย่างชัดเจน)

คอมไพเลอร์ FORTRAN 77 ส่วนใหญ่อนุญาตให้เรียกซ้ำได้บางส่วน (เช่น DEC) จำเป็นต้องใช้ตัวเลือกคอมไพเลอร์ (ดูที่บทตัวเลือกคอมไพเลอร์) GNU g77 ซึ่งสอดคล้องกับมาตรฐาน Fortran 77 อย่างเคร่งครัดไม่อนุญาตให้เรียกซ้ำ

http://www.ibiblio.org/pub/languages/fortran/ch1-12.html


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

6

ภาษาการเขียนโปรแกรม OpenCL ไม่รองรับการเรียกซ้ำ (ดูหัวข้อ 6.8 ของข้อมูลจำเพาะ OpenCL )

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

สิ่งนี้อาจนำไปใช้กับภาษาการเขียนโปรแกรม GPU อื่น ๆ เช่นภาษา Shader


2

คอมไพเลอร์ c บางตัวสำหรับไมโครคอนโทรลเลอร์ขนาดเล็กไม่รองรับการเรียกซ้ำเนื่องจากสันนิษฐานว่ามีขนาดสแต็ก จำกัด อย่างยิ่ง


ไมโครคอนโทรลเลอร์เหล่านั้นบางตัว (เช่นตระกูล PIC16) มีสแต็กการเรียกฮาร์ดแวร์เท่านั้น (ไม่สามารถเข้าถึงได้โดยคำแนะนำ) และไม่มีสแต็กรูปแบบอื่น ๆ ดังนั้นฟังก์ชั่นจึงไม่สามารถมีตัวแปรโลคอลเมื่อใช้การเรียกซ้ำ สำหรับสิ่งนั้น ... ) การอ้างอิง: en.wikipedia.org/wiki/PIC_microcontroller#Stacks
Ale

1

พื้นฐานในยุคของหมายเลขบรรทัดมักจะมีการสนับสนุนการเรียกซ้ำที่ไม่ดี BASIC จำนวนมาก (ทั้งหมด?) ในเวลานั้นรองรับการเรียก gosub ที่ซ้อนกัน แต่ไม่สนับสนุนวิธีง่ายๆในการส่งพารามิเตอร์หรือส่งคืนค่าในวิธีที่ทำให้มีประโยชน์ในการโทรด้วยตนเอง

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


1

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

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

ฉันไม่รู้ว่าสิ่งนี้สามารถเรียกว่า "สนับสนุน" ข้อเท็จจริงคือฉันเขียนฟังก์ชันแบบเรียกซ้ำด้วย ZX-Spectrum BASIC ในขณะที่ฉันทำใน Fortran77 เหมือนกับใน COBOL ... ด้วยกลอุบายนั้นเสมอ


1

ภาษาแอสเซมบลีไม่สนับสนุนการเรียกซ้ำโดยตรง - คุณต้อง "ทำเอง" โดยทั่วไปแล้วโดยการกดพารามิเตอร์ลงบนสแต็กของเครื่อง


2
รองรับการเรียกซ้ำจนถึงการรองรับการเรียกใช้เมธอด มักจะมีCALLคำสั่งซึ่งจะผลัก IP ไปที่สแต็กโดยอัตโนมัติก่อนที่จะกระโดดไปที่รูทีนย่อยและRETคำแนะนำที่ปรากฏที่อยู่ย้อนกลับเข้าไปใน IP ไม่มีเหตุผลใดที่คุณไม่สามารถCALLเข้าจุดของคุณเอง
Blorgbeard

@Blorgbeard - เป็นความจริงอย่างยิ่งแม้ว่าฉันจะยืนยันว่าสิ่งนี้ไม่เพียงพอที่จะนับเป็น "รองรับการเรียกซ้ำ" ในความหมายที่เข้าใจกันโดยทั่วไปเนื่องจากไม่ได้จัดการพารามิเตอร์ที่จำเป็นสำหรับการโทรแบบเรียกซ้ำ
mikera

1
การโทรแบบเรียกซ้ำไม่จำเป็นต้องมีพารามิเตอร์ใช่ไหม? void f() { f(); }ซ้ำ
Blorgbeard

ในทางเทคนิคแล้ว แต่ความสามารถในการเขียนโค้ดกรณีเล็ก ๆ น้อย ๆ ไม่ได้หมายความว่าคุณควรอธิบายแอสเซมบลีว่า "สนับสนุนการเรียกซ้ำ" การใช้การเรียกซ้ำแบบใช้งานจริงส่วนใหญ่ต้องการพารามิเตอร์
mikera

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