Seperti yang disarankan dalam jawaban ini , ini adalah masalah dukungan perangkat keras, meskipun tradisi dalam desain bahasa juga berperan.
ketika suatu fungsi mengembalikannya, meninggalkan sebuah pointer ke objek yang kembali dalam register tertentu
Dari tiga bahasa pertama, Fortran, Lisp dan COBOL, yang pertama menggunakan nilai pengembalian tunggal sebagaimana dimodelkan pada matematika. Yang kedua mengembalikan sejumlah parameter sewenang-wenang dengan cara yang sama seperti menerimanya: sebagai sebuah daftar (bisa juga diperdebatkan bahwa parameter hanya lulus dan mengembalikan satu parameter: alamat daftar). Yang ketiga mengembalikan nol atau satu nilai.
Bahasa-bahasa pertama ini sangat memengaruhi desain bahasa yang mengikutinya, meskipun satu-satunya yang mengembalikan banyak nilai, Lisp, tidak pernah mengumpulkan banyak popularitas.
Ketika C datang, walaupun dipengaruhi oleh bahasa sebelumnya, C memberikan fokus yang besar pada penggunaan sumber daya perangkat keras yang efisien, menjaga hubungan erat antara apa yang dilakukan oleh bahasa C dan kode mesin yang mengimplementasikannya. Beberapa fitur tertua, seperti variabel "auto" vs "register", adalah hasil dari filosofi desain itu.
Harus juga ditunjukkan bahwa bahasa assembly secara luas populer hingga tahun 80-an, ketika akhirnya mulai dihapus dari pengembangan arus utama. Orang-orang yang menulis kompiler dan membuat bahasa terbiasa dengan perakitan, dan, sebagian besar, tetap menggunakan yang terbaik di sana.
Sebagian besar bahasa yang menyimpang dari norma ini tidak pernah menemukan banyak popularitas, dan, oleh karena itu, tidak pernah memainkan peran yang kuat mempengaruhi keputusan para perancang bahasa (yang, tentu saja, terinspirasi oleh apa yang mereka ketahui).
Jadi mari kita periksa bahasa assembly. Mari kita lihat pertama pada 6502 , mikroprosesor 1975 yang terkenal digunakan oleh mikrokomputer Apple II dan VIC-20. Itu sangat lemah dibandingkan dengan apa yang digunakan dalam mainframe dan minicomputer pada waktu itu, meskipun kuat dibandingkan dengan komputer pertama 20, 30 tahun sebelumnya, pada awal bahasa pemrograman.
Jika Anda melihat deskripsi teknis, ia memiliki 5 register plus beberapa flag satu-bit. Satu-satunya register "penuh" adalah Program Counter (PC) - yang mendaftar menunjuk ke instruksi selanjutnya yang akan dieksekusi. Register lain di mana akumulator (A), dua register "indeks" (X dan Y), dan stack pointer (SP).
Memanggil subrutin menempatkan PC dalam memori yang ditunjuk oleh SP, dan kemudian menurunkan SP. Kembali dari subrutin bekerja secara terbalik. Seseorang dapat mendorong dan menarik nilai-nilai lain pada stack, tetapi sulit untuk merujuk ke memori relatif terhadap SP, sehingga menulis kembali subrutin peserta sulit. Hal yang kita anggap remeh, menyebut subrutin kapan saja kita merasa, tidak begitu umum pada arsitektur ini. Seringkali, "tumpukan" yang terpisah akan dibuat sehingga parameter dan alamat kembali subrutin akan tetap terpisah.
Jika Anda melihat prosesor yang menginspirasi 6502, 6800 , itu memiliki register tambahan, Register Index (IX), selebar SP, yang bisa menerima nilai dari SP.
Pada mesin, memanggil subrutin masuk kembali terdiri dari mendorong parameter pada stack, mendorong PC, mengubah PC ke alamat baru, dan kemudian subrutin akan mendorong variabel lokalnya pada stack . Karena jumlah variabel dan parameter lokal diketahui, mengatasinya dapat dilakukan relatif terhadap tumpukan. Misalnya, fungsi yang menerima dua parameter dan memiliki dua variabel lokal akan terlihat seperti ini:
SP + 8: param 2
SP + 6: param 1
SP + 4: return address
SP + 2: local 2
SP + 0: local 1
Itu bisa disebut berapa kali karena semua ruang sementara ada di stack.
The 8080 , digunakan pada TRS-80 dan sejumlah mikrokomputer berbasis CP / M dapat melakukan sesuatu yang mirip dengan 6800, dengan mendorong SP pada stack dan kemudian muncul pada register tidak langsungnya, HL.
Ini adalah cara yang sangat umum untuk mengimplementasikan berbagai hal, dan bahkan mendapat dukungan lebih banyak pada prosesor yang lebih modern, dengan Base Pointer yang membuat membuang semua variabel lokal sebelum kembali dengan mudah.
Masalahnya, adalah, bagaimana Anda mengembalikan sesuatu ? Register prosesor tidak terlalu banyak sejak awal, dan sering kali diperlukan beberapa dari mereka bahkan untuk mencari tahu bagian memori yang harus diatasi. Mengembalikan barang-barang di tumpukan akan menjadi rumit: Anda harus menghapus semuanya, menyimpan PC, mendorong parameter pengembalian (yang akan disimpan di mana saja?), Lalu mendorong PC lagi dan kembali.
Jadi yang biasanya dilakukan adalah memesan satu register untuk nilai pengembalian. Kode panggilan tahu nilai pengembalian akan berada di register tertentu, yang harus dipertahankan sampai dapat disimpan atau digunakan.
Mari kita lihat bahasa yang memungkinkan beberapa nilai pengembalian: Keempat. Apa yang dilakukan Forth adalah menjaga stack kembali terpisah (RP) dan tumpukan data (SP), sehingga semua fungsi harus lakukan adalah pop semua parameternya dan meninggalkan nilai kembali pada stack. Karena tumpukan kembali terpisah, itu tidak menghalangi.
Sebagai seseorang yang belajar bahasa assembly dan Forth dalam enam bulan pertama pengalaman dengan komputer, beberapa nilai pengembalian terlihat sepenuhnya normal bagi saya. Operator seperti Forth's /mod
, yang mengembalikan divisi integer dan yang lainnya, tampak jelas. Di sisi lain, saya dapat dengan mudah melihat bagaimana seseorang yang pengalaman awalnya adalah C merasa konsep itu aneh: itu bertentangan dengan harapan mereka yang mendarah daging tentang apa "fungsi" itu.
Sedangkan untuk matematika ... well, saya memprogram komputer jauh sebelum saya bisa berfungsi di kelas matematika. Ada adalah seluruh bagian dari CS dan bahasa pemrograman yang dipengaruhi oleh matematika, tapi, sekali lagi, ada seluruh bagian yang tidak.
Jadi kami memiliki pertemuan faktor-faktor di mana matematika mempengaruhi desain bahasa awal, di mana kendala perangkat keras menentukan apa yang mudah diimplementasikan, dan di mana bahasa populer mempengaruhi bagaimana perangkat keras berevolusi (mesin Lisp dan prosesor mesin Forth adalah roadkill dalam proses ini).