ตามคำแนะนำในคำตอบนี้มันเป็นเรื่องของการสนับสนุนฮาร์ดแวร์แม้ว่าประเพณีในการออกแบบภาษาก็มีบทบาท
เมื่อฟังก์ชันส่งคืนฟังก์ชันจะปล่อยให้ตัวชี้ไปยังวัตถุที่ส่งคืนในการลงทะเบียนที่ระบุ
ในสามภาษาแรกคือ Fortran, Lisp และ COBOL ซึ่งเป็นภาษาแรกที่ใช้ค่าส่งคืนเดียวเนื่องจากเป็นแบบจำลองทางคณิตศาสตร์ ที่สองส่งกลับจำนวนพารามิเตอร์โดยพลการในลักษณะเดียวกับที่ได้รับ: เป็นรายการ (อาจเป็นที่ถกเถียงกันอยู่ว่ามันผ่านและส่งกลับพารามิเตอร์เดียวเท่านั้น: ที่อยู่ของรายการ) ผลตอบแทนที่สามเป็นศูนย์หรือหนึ่งค่า
ภาษาแรกเหล่านี้มีอิทธิพลอย่างมากต่อการออกแบบของภาษาที่ตามมาแม้ว่าจะมีเพียงค่าเดียวที่คืนค่า Lisp แต่ก็ไม่เคยรวบรวมความนิยมมากนัก
เมื่อ C มาถึงแม้จะได้รับอิทธิพลจากภาษาก่อนหน้านั้นมันให้ความสำคัญอย่างมากกับการใช้ทรัพยากรฮาร์ดแวร์อย่างมีประสิทธิภาพรักษาความสัมพันธ์ที่ใกล้ชิดระหว่างสิ่งที่ภาษา C ทำกับรหัสเครื่องที่ใช้งาน คุณสมบัติที่เก่าแก่ที่สุดของมันเช่นตัวแปร "auto" vs "register" เป็นผลมาจากปรัชญาการออกแบบ
จะต้องมีการชี้ให้เห็นว่าภาษาแอสเซมบลีเป็นที่นิยมอย่างกว้างขวางจนถึงยุค 80 เมื่อในที่สุดก็เริ่มที่จะค่อย ๆ ออกจากการพัฒนาที่สำคัญ คนที่เขียนคอมไพเลอร์และภาษาที่สร้างจะคุ้นเคยกับการชุมนุมและส่วนใหญ่เก็บไว้ในสิ่งที่ทำงานได้ดีที่สุดที่นั่น
ภาษาส่วนใหญ่ที่แยกออกจากบรรทัดฐานนี้ไม่เคยได้รับความนิยมมากนักและดังนั้นจึงไม่เคยมีบทบาทที่แข็งแกร่งที่มีอิทธิพลต่อการตัดสินใจของนักออกแบบภาษา (แน่นอนว่าเป็นแรงบันดาลใจจากสิ่งที่พวกเขารู้)
ลองดูภาษาแอสเซมบลีกัน ก่อนอื่นมาดูที่6502ซึ่งเป็นไมโครโพรเซสเซอร์ 1975 ซึ่งถูกใช้อย่างมีชื่อเสียงโดยไมโครคอมพิวเตอร์ Apple II และ VIC-20 มันอ่อนแอมากเมื่อเทียบกับสิ่งที่ใช้ในเมนเฟรมและ minicomputers ของเวลาแม้ว่าทรงพลังเมื่อเทียบกับคอมพิวเตอร์เครื่องแรกของ 20, 30 ปีก่อนในตอนเช้าของภาษาโปรแกรม
ถ้าคุณดูที่คำอธิบายทางเทคนิคมันมี 5 รีจิสเตอร์พร้อมกับแฟล็กหนึ่งบิต การลงทะเบียน "เต็ม" เพียงอย่างเดียวคือ Program Counter (PC) - ที่ลงทะเบียนคะแนนไปยังคำสั่งถัดไปที่จะดำเนินการ รีจิสเตอร์อื่นโดยที่ตัวสะสม (A), สอง "ดัชนี" รีจิสเตอร์ (X และ Y) และตัวชี้สแต็ก (SP)
การเรียกรูทีนย่อยทำให้พีซีอยู่ในหน่วยความจำที่ชี้ไปยัง SP จากนั้นลด SP ลง การกลับมาจากรูทีนย่อยทำงานในสิ่งที่ตรงกันข้าม หนึ่งสามารถผลักดันและดึงค่าอื่น ๆ บนสแต็ก แต่เป็นการยากที่จะอ้างถึงหน่วยความจำที่เกี่ยวข้องกับ SP ดังนั้นการเขียนรูทีนย่อยผู้เข้าร่วมใหม่จึงเป็นเรื่องยาก สิ่งนี้ที่เรารับอนุญาตเรียกรูทีนย่อยเมื่อใดก็ตามที่เรารู้สึกว่าไม่ธรรมดาในสถาปัตยกรรมนี้ บ่อยครั้งจะมีการสร้าง "สแต็ก" แยกต่างหากเพื่อให้พารามิเตอร์และที่อยู่ผู้ส่งคืนรูทีนย่อยถูกเก็บแยกต่างหาก
หากคุณดูโปรเซสเซอร์ที่เป็นแรงบันดาลใจ 6502, 6800จะมีการลงทะเบียนเพิ่มเติม, ดัชนีการลงทะเบียน (IX), กว้างเท่ากับ SP ซึ่งสามารถรับค่าจาก SP
บนเครื่องการเรียกรูทีนย่อยกลับเข้ามาใหม่ประกอบด้วยการผลักดันพารามิเตอร์บนสแต็คผลักพีซีเปลี่ยนพีซีเป็นที่อยู่ใหม่จากนั้นรูทีนย่อยจะผลักดันตัวแปรโลคัลบนสแต็ก เนื่องจากทราบจำนวนตัวแปรและพารามิเตอร์โลคัลการกำหนดแอดเดรสจึงสามารถทำได้โดยสัมพันธ์กับสแต็ก ตัวอย่างเช่นฟังก์ชั่นที่รับพารามิเตอร์สองตัวและการมีตัวแปรโลคัลสองตัวจะมีลักษณะดังนี้:
SP + 8: param 2
SP + 6: param 1
SP + 4: return address
SP + 2: local 2
SP + 0: local 1
สามารถเรียกได้หลายครั้งเพราะพื้นที่ชั่วคราวทั้งหมดอยู่บนสแต็ก
8080 , ใช้ใน TRS-80 และโฮสต์ของ CP / M-ไมโครคอมพิวเตอร์ที่ใช้สามารถทำบางสิ่งบางอย่างที่คล้ายกับ 6800 โดยการผลักดัน SP ในกองแล้ว popping มันเกี่ยวกับการลงทะเบียนโดยทางอ้อม, HL
นี่เป็นวิธีการทั่วไปในการนำสิ่งต่าง ๆ มาใช้และได้รับการสนับสนุนมากขึ้นในตัวประมวลผลที่ทันสมัยยิ่งขึ้นด้วย Base Pointer ที่ทำให้การทิ้งตัวแปรท้องถิ่นทั้งหมดก่อนที่จะกลับมาง่าย
ปัญหาที่เกิดขึ้นเป็นอย่างไรคุณกลับอะไร ? ตัวประมวลผลการลงทะเบียนไม่ได้เริ่มเร็วนักและมักจำเป็นต้องใช้บางอย่างเพื่อหาหน่วยความจำส่วนใด การคืนสิ่งต่าง ๆ บนสแต็กจะซับซ้อน: คุณต้องป๊อปอัพทุกอย่างบันทึกพีซีดันพารามิเตอร์ที่ส่งคืน (ซึ่งจะถูกเก็บไว้ที่ไหน?) จากนั้นกดพีซีอีกครั้ง
ดังนั้นสิ่งที่มักจะทำคือจองหนึ่งทะเบียนสำหรับค่าส่งคืน รหัสการโทรรู้ว่าค่าส่งคืนจะอยู่ในการลงทะเบียนเฉพาะซึ่งจะต้องเก็บรักษาไว้จนกว่าจะสามารถบันทึกหรือใช้งานได้
ลองดูภาษาที่อนุญาตการคืนค่าหลาย ๆ ค่า: Forth สิ่งที่ Forth ทำคือการรักษา stack stack (RP) และ data stack (SP) ที่แยกต่างหากเพื่อให้ฟังก์ชั่นทั้งหมดที่ต้องทำคือ pop พารามิเตอร์ทั้งหมดและเก็บค่าส่งคืนบนสแต็ก เนื่องจากสแต็กส่งคืนแยกจากกันจึงไม่สามารถเข้าถึงได้
ในฐานะคนที่เรียนรู้ภาษาแอสเซมบลีและ Forth ในช่วงหกเดือนแรกของประสบการณ์กับคอมพิวเตอร์ ตัวดำเนินการเช่น Forth's /mod
ซึ่งคืนค่าการแบ่งจำนวนเต็มและส่วนที่เหลือดูเหมือนจะชัดเจน ในทางกลับกันฉันสามารถเห็นได้อย่างง่ายดายว่าคนที่มีประสบการณ์ในช่วงต้นคือ C ใจพบแนวคิดที่แปลก: มันขัดกับความคาดหวังที่ฝังแน่นของพวกเขาในสิ่งที่ "ฟังก์ชั่น" คืออะไร
ส่วนคณิตศาสตร์ ... ก็ฉันเขียนโปรแกรมทางคอมพิวเตอร์ก่อนที่ฉันจะเข้าฟังก์ชั่นในวิชาคณิตศาสตร์ มีเป็นทั้งส่วนของการบริการลูกค้าและการเขียนโปรแกรมภาษาซึ่งได้รับอิทธิพลจากคณิตศาสตร์ แต่แล้วอีกครั้งมีทั้งส่วนที่ไม่ได้
ดังนั้นเราจึงมีการรวมตัวกันของปัจจัยที่คณิตศาสตร์มีอิทธิพลต่อการออกแบบภาษายุคแรก ๆ ที่ข้อ จำกัด ของฮาร์ดแวร์กำหนดสิ่งที่นำไปปฏิบัติได้ง่ายและที่ภาษายอดนิยมมีอิทธิพลต่อการพัฒนาฮาร์ดแวร์ (เครื่อง Lisp และโปรเซสเซอร์จากเครื่อง