Mengapa perpustakaan standar bukan bahasa pemrograman primitif? [Tutup]


30

Saya berpikir mengapa ada (dalam semua bahasa pemrograman yang telah saya pelajari, seperti C ++, Java, Python) pustaka standar seperti stdlib, alih-alih memiliki "fungsi" yang sama menjadi primitif dari bahasa itu sendiri.


4
Apa maksud Anda "mengapa kompiler tidak bisa menerjemahkan panggilan fungsi ke dalam sekumpulan instruksi"? Itulah kira-kira apa yang dilakukan kompiler, pustaka standar atau tidak (Ok, Python hanya separuh dan bytecode Java to JVM; konsep serupa). Pustaka standar benar-benar tidak ada hubungannya dengan kompilasi kode -> instruksi.
Delioth

25
@Delioth Saya pikir Simone bertanya mengapa tidak semua yang ada di perpustakaan standar bahasa $ LANG merupakan konstruksi / fungsi primitif dari bahasa itu. Saya akan mengatakan itu adalah pertanyaan yang masuk akal bagi siapa saja yang sangat baru dalam bahasa pemrograman :)
Andres F.

33
Pustaka standar umumnya mengisi kesenjangan antara bahasa pemrograman yang bekerja dan yang bermanfaat yang akan digunakan orang.
Telastyn

6
Bagian penting dari pustaka standar Python sebenarnya ditulis dalam C dan sudah dikompilasi.
ElmoVanKielmo

1
Sebagai cara kontras, dalam sebagian besar implementasi BASIC semuanya adalah bagian dari bahasa dan tidak ada perpustakaan sama sekali atau dukungan untuk mereka (kecuali, dalam beberapa implementasi, untuk kemampuan untuk memanggil rutinitas bahasa mesin).
Euro Micelli

Jawaban:


32

Izinkan saya untuk sedikit memperluas jawaban yang baik (@) dari @ Vincent :

Mengapa kompiler tidak dapat menerjemahkan panggilan fungsi ke dalam sekumpulan instruksi?

Itu bisa, dan melakukannya melalui setidaknya dua mekanisme:

  • inlining panggilan fungsi - selama penerjemahan, kompiler dapat mengganti panggilan kode sumber dengan implementasinya langsung sebaris alih-alih membuat panggilan aktual ke fungsi. Masih fungsi perlu memiliki implementasi yang ditentukan di suatu tempat dan itu bisa di perpustakaan standar.

  • fungsi intrinsik - intrinsik adalah fungsi yang telah diinformasikan oleh kompiler tanpa harus menemukan fungsi di perpustakaan. Ini biasanya disediakan untuk fitur perangkat keras yang secara praktis tidak dapat diakses dengan cara lain, menjadi sangat sederhana sehingga bahkan overhead panggilan ke fungsi perpustakaan bahasa assembly dianggap tinggi. (Kompilator umumnya hanya secara otomatis memasukkan kode sumber dalam bahasanya, tetapi tidak fungsi-fungsi perakitan, yang merupakan mekanisme intrinsik.)

Masih ini dikatakan, opsi terbaik kadang-kadang adalah untuk kompiler untuk menerjemahkan panggilan fungsi dalam bahasa sumber menjadi panggilan fungsi dalam kode mesin. Rekursi, metode virtual, dan ukuran tipis adalah beberapa alasan yang membuat inlining tidak selalu memungkinkan / praktis. (Alasan lain adalah maksud dari pembangunan, seperti kompilasi terpisah (modul objek), unit beban terpisah (misalnya DLL)).

Tidak ada keuntungan nyata untuk membuat sebagian besar fungsi perpustakaan standar intrisik (yang akan menyulitkan kode lebih banyak pengetahuan ke dalam kompiler tanpa keuntungan nyata), jadi panggilan kode mesin lagi sering paling tepat.

C adalah bahasa yang terkenal yang bisa menghilangkan pernyataan bahasa eksplisit lainnya yang mendukung fungsi perpustakaan standar. Meskipun perpustakaan sudah ada sebelumnya, bahasa ini membuat pergeseran untuk melakukan lebih banyak pekerjaan dari fungsi perpustakaan standar dan kurang sebagai pernyataan eksplisit dalam tata bahasa. IO dalam bahasa lain, misalnya, sering diberikan sintaksisnya sendiri dalam bentuk berbagai pernyataan, sedangkan tata bahasa C tidak mendefinisikan pernyataan IO apa pun, alih-alih menunda ke perpustakaan standarnya untuk menyediakan, semua dapat diakses melalui pemanggilan fungsi, yang kompiler sudah tahu caranya.


3
Jawaban bagus. Orang harus menambahkan beberapa kata mengapa keputusan ini dalam C dibuat: jika saya ingat dengan benar, alasan utama sebenarnya karena membuatnya lebih mudah untuk membuat kompiler C untuk banyak arsitektur perangkat keras yang berbeda.
Doc Brown

10
@DocBrown Pada tahun 1975, ada cukup banyak contoh di bidang pengembangan bahasa pemrograman (ALGOL-68, ada?) Yang menunjukkan bahwa upaya untuk memasukkan semuanya ke dalam bahasa secara langsung menyebabkan penurunan yang cukup besar baik dalam memenuhi spesifikasi bahasa dan dalam menghasilkan implementasi bahasa.
Joker_vD

5
Contoh serupa adalah apa yang Python lakukan dengan print: Dalam 2.x, itu adalah pernyataan , dengan tata bahasa khusus sendiri, tetapi dalam 3.x, itu hanya menjadi pemanggilan fungsi lain. Lihat PEP 3105 untuk penjelasan resmi.
dan04

1
@DocBrown, portabilitas hampir pasti bukan alasan. Ketika Unix dan C dibuat, mereka dirancang dan dibangun untuk satu mesin, sebuah PDP-7 cadangan, ketika Ken Thompson bertanya-tanya konsep apa yang bisa diselamatkan dari proyek Multics yang gagal. C juga diciptakan karena satu alasan: untuk memiliki bahasa tingkat tinggi untuk (kembali) mengimplementasikan Unix. Mereka pada dasarnya kami adalah percobaan dalam desain perangkat lunak, bukan upaya serius pada OS multi-platform komersial dan bahasa. Lihat bell-labs.com/usr/dmr/www/chist.html misalnya.
Euro Micelli

@EuroMicelli: Saya tidak melihat ada kontradiksi. Dan referensi Anda mengandung banyak detail tentang kapan portabilitas menjadi penting, itu sebenarnya di tahun-tahun awal pengembangan C dan Unix. Saya hanya bisa menebak di sini, tetapi jika para penemu C tidak akan membiarkan bahasa itu sengaja dibuat kecil, saya pikir itu akan sangat tidak mungkin bahwa mereka bisa mengangkutnya begitu cepat dan berhasil ke banyak arsitektur yang berbeda.
Doc Brown

70

Ini hanya untuk menjaga bahasa itu sendiri sesederhana mungkin. Anda perlu membedakan antara fitur bahasa, seperti jenis loop atau cara untuk menyampaikan parameter ke fungsi dan sebagainya, dan fungsi umum yang dibutuhkan sebagian besar aplikasi.

Perpustakaan adalah fungsi yang mungkin berguna bagi banyak programmer sehingga mereka dibuat sebagai kode yang dapat digunakan kembali yang dapat dibagikan. Perpustakaan standar dirancang untuk menjadi fungsi yang sangat umum yang biasanya dibutuhkan oleh pemrogram. Dengan cara ini, bahasa pemrograman segera bermanfaat bagi beragam programmer. Perpustakaan dapat diperbarui dan diperluas tanpa mengubah fitur inti dari bahasa itu sendiri.


3
Tidak selalu. PHPsebagai contoh sulit membuat perbedaan antara fungsi bahasanya yang luas dan bahasanya sendiri.
Vahid Amiri

15
Saya tidak akan mengambil PHP sebagai contoh bahasa yang sederhana
DrBreakalot

3
@DrBreakalot PHP adalah bahasa yang sangat sederhana. Itu bukan untuk mengatakan bahwa ia memiliki desain yang konsisten, tetapi itu masalah lain.
Lightness Races dengan Monica

19
@LightnessRacesinOrbit Saya tidak akan menyebut PHP "sederhana" sama sekali: ia memiliki sistem objek berbasis kelas, satu set terpisah 'nilai primitif', fungsi mandiri, penutupan kelas satu dibangun pada sistem objek, mekanisme namespace, berbagai gagasan yang disebut "static", pernyataan serta ekspresi, include, requiredan require_once, jika / untuk / sementara (pemrograman terstruktur), pengecualian, suatu sistem yang terpisah dari 'kesalahan nilai-nilai', rumit aturan mengetik lemah, rumit peraturan operator didahulukan, dan seterusnya . Bandingkan ini dengan kesederhanaan, katakanlah, Smalltalk, Skema, Prolog, Keempat, dll;)
Warbo

3
Alasan utama, yang diisyaratkan tetapi tidak secara eksplisit dinyatakan dalam jawaban ini, adalah bahwa dengan menjaga bahasa sesederhana mungkin, jauh lebih mudah untuk diterapkan pada platform lain. Karena perpustakaan standar biasanya ditulis dalam bahasa itu sendiri , mereka dapat dengan mudah diporting.
BlueRaja - Danny Pflughoeft

34

Selain apa yang sudah dikatakan oleh jawaban lain, menempatkan fungsi standar ke perpustakaan adalah pemisahan dari keprihatinan :

  • Adalah tugas kompiler untuk mengurai bahasa dan menghasilkan kode untuk itu. Bukan tugas kompiler untuk memuat apa pun yang sudah bisa ditulis dalam bahasa itu dan disediakan sebagai perpustakaan.

  • Ini pekerjaan perpustakaan standar (yang selalu tersedia secara implisit) untuk menyediakan fungsionalitas inti yang dibutuhkan oleh hampir semua program. Bukan tugas perpustakaan standar untuk memuat semua fungsi yang mungkin berguna.

  • Merupakan tugas pustaka standar opsional untuk menyediakan fungsionalitas bantu yang dapat dilakukan tanpa banyak program, tetapi yang masih cukup mendasar dan juga penting bagi banyak aplikasi untuk menjamin pengiriman dengan lingkungan standar. Bukan tugas pustaka opsional untuk memuat semua kode yang dapat digunakan kembali yang pernah ditulis.

  • Merupakan tugas pustaka pengguna untuk menyediakan koleksi fungsi yang dapat digunakan kembali yang berguna. Bukan tugas pustaka pengguna untuk memuat semua kode yang pernah ditulis.

  • Merupakan tugas kode sumber aplikasi untuk menyediakan bit kode yang tersisa yang benar-benar hanya relevan dengan satu aplikasi itu.

Jika Anda menginginkan perangkat lunak satu ukuran untuk semua, Anda mendapatkan sesuatu yang sangat rumit. Anda perlu memodulasi untuk menurunkan kompleksitas ke tingkat yang dapat dikelola. Dan Anda perlu memodulasi untuk memungkinkan implementasi parsial :

  • Pustaka threading tidak berguna pada pengontrol tertanam satu inti. Mengizinkan implementasi bahasa untuk pengontrol tertanam ini tidak menyertakan pthreadperpustakaan adalah hal yang tepat untuk dilakukan.

  • Perpustakaan matematika tidak berharga pada pengontrol mikro yang bahkan tidak memiliki FPU. Sekali lagi, tidak dipaksa untuk menyediakan fungsi seperti sin()membuat hidup jauh lebih mudah bagi implementator bahasa Anda untuk mikrokontroler itu.

  • Bahkan pustaka standar inti tidak bernilai saat Anda memprogram kernel. Anda tidak dapat menerapkan write()tanpa syscall ke dalam kernel, dan Anda tidak dapat menerapkan printf()tanpa write(). Sebagai pemrogram kernel, tugas Anda untuk menyediakan write()syscall, Anda tidak bisa hanya mengharapkannya ada di sana.

Bahasa yang tidak memungkinkan untuk penghapusan seperti itu dari perpustakaan standar sama sekali tidak cocok untuk banyak tugas . Jika Anda ingin bahasa Anda dapat digunakan secara fleksibel di lingkungan yang tidak umum, itu harus fleksibel dalam apa yang termasuk pustaka standar. Semakin banyak bahasa Anda bergantung pada perpustakaan standar, semakin banyak asumsi yang dibuatnya pada lingkungan eksekusinya, dan karenanya membatasi penggunaannya pada lingkungan yang menyediakan prasyarat ini.

Tentu saja, bahasa tingkat tinggi seperti python dan java dapat membuat banyak asumsi tentang lingkungan mereka. Dan mereka cenderung memasukkan banyak, banyak hal ke dalam perpustakaan standar mereka. Bahasa tingkat rendah seperti C menyediakan lebih sedikit di perpustakaan standar mereka, dan menjaga perpustakaan standar inti jauh lebih kecil. Itu sebabnya Anda menemukan kompiler C yang berfungsi untuk hampir semua arsitektur, tetapi mungkin tidak dapat menjalankan skrip python di atasnya.


16

Salah satu alasan utama kompiler dan perpustakaan standar terpisah adalah karena mereka melayani dua tujuan yang berbeda (bahkan jika keduanya didefinisikan oleh spesifikasi bahasa yang sama): kompiler menerjemahkan kode tingkat yang lebih tinggi ke dalam instruksi mesin, dan perpustakaan standar menyediakan pra-uji implementasi fungsionalitas yang biasanya dibutuhkan. Nilai kompiler penulis modularitas sama seperti pengembang perangkat lunak lainnya. Bahkan, beberapa kompiler C awal lebih lanjut membagi kompiler menjadi program terpisah untuk pra-pemrosesan, kompilasi, dan penautan.

Modularitas ini memberi Anda banyak keuntungan:

  • Ini meminimalkan jumlah pekerjaan yang diperlukan ketika mendukung platform perangkat keras baru, karena sebagian besar kode perpustakaan standar adalah perangkat keras-agnostik dapat digunakan kembali.
  • Implementasi perpustakaan standar dapat dioptimalkan dengan berbagai cara (untuk kecepatan, untuk ruang, untuk penggunaan sumber daya, dll). Banyak sistem komputasi awal hanya memiliki satu kompiler yang tersedia, dan memiliki perpustakaan standar yang terpisah berarti pengembang dapat bertukar implementasi sesuai dengan kebutuhan mereka.
  • Fungsi pustaka standar bahkan tidak harus ada. Ketika menulis kode C logam biasa, Anda memiliki kompiler berfitur lengkap tetapi sebagian besar fungsi pustaka standar tidak ada dan beberapa hal seperti file I / O bahkan tidak mungkin. Jika kompiler diperlukan untuk mengimplementasikan fungsi ini, maka Anda tidak dapat memiliki kompiler C yang memenuhi standar pada beberapa platform di mana Anda paling membutuhkannya.
  • Pada sistem awal, kompiler sering dikembangkan oleh perusahaan yang mendesain perangkat keras. Pustaka standar sering disediakan oleh vendor OS, karena mereka sering membutuhkan akses ke fungsionalitas (seperti panggilan sistem) khusus untuk platform perangkat lunak itu. Itu tidak praktis untuk penulis kompiler harus mendukung semua kombinasi yang berbeda dari perangkat keras dan perangkat lunak (dulu ada banyak variasi lebih baik di kedua arsitektur perangkat keras dan platform perangkat lunak).
  • Dalam bahasa tingkat tinggi, perpustakaan standar dapat diimplementasikan sebagai perpustakaan yang dimuat secara dinamis. Satu implementasi perpustakaan standar kemudian dapat digunakan oleh banyak kompiler dan / atau bahasa pemrograman.

Secara historis (setidaknya dari perspektif C), versi asli, pra-standardisasi bahasa tidak memiliki perpustakaan standar sama sekali. Vendor OS dan pihak ketiga sering menyediakan perpustakaan yang penuh dengan fungsi yang umum digunakan, tetapi implementasi yang berbeda termasuk hal yang berbeda dan mereka sebagian besar tidak kompatibel satu sama lain. Ketika C distandarisasi, mereka mendefinisikan "perpustakaan standar" dalam upaya untuk menyelaraskan implementasi yang berbeda ini dan meningkatkan portabilitas. Pustaka standar C dikembangkan terpisah dari bahasa, seperti yang dimiliki pustaka Boost untuk C ++, tetapi kemudian diintegrasikan ke dalam spek bahasa.


6

Jawaban tambahan untuk kasus sudut: Manajemen kekayaan intelektual

Contoh penting adalah implementasi Math.Pow (dobel, dobel) dalam .NET Framework yang dibeli oleh Microsoft dari Intel dan tetap dirahasiakan bahkan jika kerangka kerjanya open-source. (Tepatnya, dalam kasus di atas itu adalah panggilan internal daripada perpustakaan tetapi ide itu berlaku.) Perpustakaan yang terpisah dari bahasa itu sendiri (secara teoritis juga merupakan subset dari perpustakaan standar) dapat memberikan fleksibilitas yang lebih besar kepada para pendukung bahasa dalam menggambar batas antara apa yang harus tetap transparan dan apa yang harus tetap tidak diungkapkan (karena kontrak mereka dengan pihak ke-3 atau alasan terkait IP lainnya).


Ini membingungkan. Halaman yang Anda tautkan tentang Math.Powtidak menyebutkan pembelian apa pun, atau apa pun tentang Intel, dan berbicara tentang orang-orang yang membaca kode sumber penerapan fungsi.
Lightness Races dengan Monica

@LightnessRacesinOrbit - hm, saya masih bisa melihatnya di sana (saat mencari "intel"). Anda juga dapat menemukan referensi ke kode sumber terbaru (di komentar terbaru) dan juga implementasi alternatif (dalam jawaban kedua) yang tersedia untuk umum tetapi kompleksitas dan berkomentar ketidakefisienan yang memberikan petunjuk mengapa implementasi asli masih belum diungkapkan. Implementasi yang benar-benar efisien mungkin memerlukan pengetahuan mendalam tentang banyak detail pada level CPU yang belum tentu tersedia dalam domain publik.
miroxlav

5

Bug dan debugging.

Bug: Semua perangkat lunak memiliki bug, perpustakaan standar Anda memiliki bug dan kompiler Anda memiliki bug. Sebagai pengguna bahasa, jauh lebih mudah untuk menemukan dan mengatasinya ketika bug tersebut ada di perpustakaan standar dibandingkan dengan di kompiler.

Debugging: Jauh lebih mudah bagi saya untuk melihat setumpuk perpustakaan standar dan memberi saya beberapa pengertian tentang apa yang mungkin salah. Karena jejak stack memiliki kode yang saya mengerti. Tentu Anda dapat menggali lebih dalam dan Anda juga dapat melacak fungsi intrinsik Anda, tetapi itu jauh lebih mudah jika dalam bahasa yang Anda gunakan sepanjang waktu dari hari ke hari.


5

Ini adalah pertanyaan yang sangat bagus!

Keadaan Seni

Standar C ++, misalnya, tidak pernah menentukan apa yang harus diimplementasikan dalam kompiler atau di perpustakaan standar: itu hanya merujuk pada implementasi . Sebagai contoh, simbol-simbol yang dilindungi didefinisikan baik oleh kompiler (sebagai intrinsik) dan oleh perpustakaan standar, secara bergantian.

Namun, semua implementasi C ++ yang saya tahu akan memiliki jumlah intrinsik seminimal mungkin yang disediakan oleh kompiler, dan sebanyak mungkin disediakan oleh pustaka standar.

Jadi, sementara secara teknis layak untuk mendefinisikan perpustakaan standar sebagai fungsi intrinsik dalam kompiler, tampaknya jarang digunakan dalam praktik.

Mengapa?

Mari kita pertimbangkan gagasan untuk memindahkan sebagian fungsionalitas dari pustaka standar ke kompiler.

Keuntungan:

  • Diagnosis yang lebih baik: intrinsik dapat dibuat khusus.
  • Kinerja yang lebih baik: intrinsik dapat dibuat khusus.

Kekurangan:

  • Peningkatan massa kompiler: setiap kasing menambah kompleksitas pada kompiler; kompleksitas meningkatkan biaya perawatan, dan kemungkinan bug.
  • Iterasi yang lebih lambat: mengubah implementasi fungsi memerlukan pengubahan kompiler itu sendiri, membuatnya lebih sulit untuk membuat perpustakaan kecil (di luar std) untuk bereksperimen.
  • Semakin tinggi bar untuk masuk: semakin mahal / semakin sulit mengubah sesuatu, semakin sedikit orang yang mau terjun.

Ini berarti bahwa memindahkan sesuatu ke kompiler itu mahal , sekarang dan di masa depan, dan oleh karena itu memerlukan case yang solid. Untuk beberapa bagian fungsionalitas, perlu (mereka tidak dapat ditulis sebagai kode biasa), namun meskipun demikian membayar untuk mengekstraksi potongan-potongan minimal dan generik untuk pindah ke kompiler dan membangun di atasnya di perpustakaan standar.


5

Sebagai perancang bahasa sendiri, saya ingin menggaungkan beberapa jawaban lain di sini, tetapi berikan melalui mata seseorang yang sedang membangun suatu bahasa.

API belum selesai saat Anda selesai menambahkan semua yang Anda bisa ke dalamnya. API selesai saat Anda selesai mengambil semua yang Anda bisa darinya.

Bahasa pemrograman harus ditentukan menggunakan beberapa bahasa. Anda harus dapat menyampaikan makna di balik program apa pun yang ditulis dalam bahasa Anda. Bahasa ini sangat sulit untuk ditulis, dan bahkan lebih sulit untuk menulis dengan baik. Secara umum, ini cenderung menjadi bentuk bahasa Inggris yang sangat tepat dan terstruktur yang digunakan untuk menyampaikan makna bukan kepada komputer, tetapi untuk pengembang lain, terutama pengembang yang menulis kompiler atau penerjemah untuk bahasa Anda. Berikut ini contoh dari spesifikasi C ++ 11, [intro.multithread / 14]:

Urutan efek samping yang terlihat pada objek atom M, sehubungan dengan perhitungan nilai B dari M, adalah sub-urutan efek samping berdekatan maksimum dalam urutan modifikasi M, di mana efek samping pertama terlihat sehubungan dengan B , dan untuk setiap efek samping, bukan itu yang terjadi B sebelum itu. Nilai objek atom M, sebagaimana ditentukan oleh evaluasi B, harus merupakan nilai yang disimpan oleh beberapa operasi dalam urutan M yang terlihat sehubungan dengan B. [Catatan: Dapat ditunjukkan bahwa urutan efek samping dari nilai yang terlihat. perhitungan unik karena persyaratan koherensi di bawah ini. —Kirim catatan]

Blek! Siapa pun yang telah mengambil risiko untuk memahami bagaimana C ++ 11 menangani multithreading dapat menghargai mengapa kata-kata itu harus sangat buram, tetapi itu tidak memaafkan fakta bahwa itu ... yah ... begitu buram!

Bandingkan dengan definisi std::shared_ptr<T>::reset, di bagian perpustakaan standar:

template <class Y> void reset(Y* p);

Efek: Setara denganshared_ptr(p).swap(*this)

Jadi apa bedanya? Pada bagian definisi bahasa, penulis tidak dapat berasumsi bahwa pembaca memahami primitif bahasa. Semuanya harus ditentukan dengan cermat dalam prosa bahasa Inggris. Setelah kita sampai ke bagian definisi perpustakaan, kita dapat menggunakan bahasa untuk menentukan perilaku. Ini seringkali jauh lebih mudah!

Pada prinsipnya, seseorang dapat memiliki membangun yang mulus dari primitif pada awal dokumen spesifikasi, sepanjang mendefinisikan apa yang akan kita pikirkan sebagai "fitur perpustakaan standar", tanpa harus menarik garis antara "primitif bahasa" dan fitur "perpustakaan standar". Dalam praktiknya, garis itu terbukti sangat berharga untuk digambar karena memungkinkan Anda menulis beberapa bagian bahasa yang paling rumit (seperti yang harus menerapkan algoritma) menggunakan bahasa yang dirancang untuk mengekspresikannya.

Dan kami memang melihat beberapa garis buram:

  • Di Jawa, java.lang.ref.Reference<T>mungkin hanya disubklasifikasikan oleh kelas perpustakaan standar java.lang.ref.WeakReference<T> java.lang.ref.SoftReference<T>dan java.lang.ref.PhantomReference<T>karena perilaku Referencesangat terkait dengan spesifikasi bahasa Jawa sehingga mereka perlu membatasi beberapa bagian dari proses yang diimplementasikan sebagai kelas "perpustakaan standar".
  • Di C #, ada kelas, System.Delegate yang merangkum konsep delegasi. Meskipun namanya, itu bukan delegasi. Ini juga merupakan kelas abstrak (tidak dapat dipakai) yang Anda tidak dapat membuat kelas turunan dari. Hanya sistem yang dapat melakukannya melalui fitur yang ditulis dalam spesifikasi bahasa.

2

Ini dimaksudkan sebagai tambahan untuk jawaban yang ada (dan terlalu panjang untuk dikomentari).

Setidaknya ada dua alasan lain untuk perpustakaan standar:

Penghalang untuk Masuk

Jika fitur bahasa tertentu dalam fungsi perpustakaan dan saya ingin tahu cara kerjanya, saya bisa membaca sumber untuk fungsi itu. Jika saya ingin mengirimkan laporan bug / tambalan / permintaan tarik, biasanya tidak terlalu sulit untuk membuat kode kasus perbaikan dan pengujian. Jika ada di kompiler, saya harus dapat menggali internal. Bahkan jika itu dalam bahasa yang sama (dan memang harus demikian, kompiler yang menghargai diri sendiri harus di-host sendiri) kode kompiler tidak seperti kode aplikasi. Mungkin diperlukan selamanya bahkan untuk menemukan file yang benar.

Anda memutuskan diri dari banyak kontributor potensial jika Anda menempuh rute itu.

Memuat kode panas

Banyak bahasa menawarkan fitur ini sampai tingkat tertentu, tetapi akan sangat rumit untuk memuat ulang kode yang melakukan pemuatan ulang yang panas. Jika SL terpisah dari runtime, ia dapat dimuat ulang.


3
"Kompilator yang menghargai diri sendiri harus di-host-sendiri" - tidak sama sekali. Tidak ada gunanya untuk memiliki versi mengatakan LLVM ditulis dalam C, C ++, Objective-C, Swift, Fortran dan sebagainya untuk mengkompilasi semua bahasa ini.
gnasher729

@ gnasher729 bukankah itu sedikit kasus khusus (bersama dengan target multi bahasa lainnya seperti CLR)?
Jared Smith

@ JaredSmith Saya akan mengatakan ini adalah kasus umum, tidak istimewa sama sekali. Tidak ada yang menulis "kompiler" sebagai aplikasi monolitik lagi. Mereka menghasilkan sistem kompiler sebagai gantinya. Sebagian besar fungsi kompiler komplit sepenuhnya independen dari bahasa tertentu yang sedang dikompilasi, dan sebagian besar bagian yang bergantung pada bahasa dapat dilakukan dengan menyediakan data yang berbeda yang mendefinisikan tata bahasa, bukan dengan menulis kode berbeda untuk setiap bahasa yang Anda gunakan. ingin dikompilasi.
alephzero

2

Ini adalah pertanyaan menarik tetapi ada banyak jawaban bagus yang sudah diberikan, jadi saya tidak akan mencoba yang lengkap.

Namun, dua hal yang menurut saya kurang mendapat perhatian:

Pertama adalah bahwa semuanya bukan potongan super jernih. Ini sedikit spektrum persis karena ada alasan untuk melakukan sesuatu secara berbeda. Sebagai contoh, kompiler sering tahu tentang perpustakaan standar dan fungsinya. Contoh dari contoh: Fungsi "Hello World" C - printf - adalah yang terbaik yang dapat saya pikirkan. Ini adalah fungsi perpustakaan, itu semacam harus, karena sangat tergantung platform. Tapi itu perilaku (implementasi didefinisikan) perlu diketahui oleh kompiler untuk memperingatkan programmer tentang doa yang buruk. Ini tidak terlalu rapi, tetapi dipandang sebagai kompromi yang baik. Kebetulan, ini adalah jawaban nyata untuk sebagian besar pertanyaan "mengapa desain ini": banyak kompromi dan "sepertinya ide yang bagus pada saat itu". Tidak selalu "ini adalah cara yang jelas untuk melakukannya" atau "

Kedua adalah memungkinkan perpustakaan standar untuk tidak menjadi semua standar itu. Ada banyak situasi di mana bahasa diinginkan tetapi perpustakaan standar yang biasanya menyertainya tidak praktis dan diinginkan. Ini paling sering terjadi dengan bahasa pemrograman sistem seperti C, pada platform non-standar. Misalnya, jika Anda memiliki sistem tanpa OS atau penjadwal: Anda tidak akan memiliki threading.

Dengan model perpustakaan standar (dan threading didukung di dalamnya) ini dapat ditangani dengan bersih: kompilernya hampir sama, Anda dapat menggunakan kembali bit perpustakaan yang berlaku, dan apa pun yang tidak dapat Anda hapus. Jika ini dimasukkan ke dalam kompiler, hal-hal mulai menjadi berantakan.

Sebagai contoh:

  • Anda tidak bisa menjadi kompiler yang patuh.

  • Bagaimana Anda menunjukkan penyimpangan Anda dari standar. Catatan biasanya ada beberapa bentuk impor / sertakan sintaks Anda dapat gagal yaitu impor ular sanca atau C's yang dengan mudah menunjukkan masalah jika ada sesuatu yang hilang dalam model perpustakaan standar.

Masalah serupa juga berlaku jika Anda ingin mengubah atau memperluas fungsionalitas 'perpustakaan'. Ini jauh lebih umum daripada yang Anda kira. Hanya untuk bertahan dengan threading: windows, linux dan beberapa unit pemrosesan jaringan eksotis semua melakukan threading sangat berbeda. Sementara bit linux / windows mungkin cukup statis dan dapat menggunakan API yang identik, hal-hal NPU akan berubah dengan hari dalam seminggu dan API dengannya. Compiler akan dengan cepat menyimpang ketika orang memutuskan bit mana yang mereka butuhkan untuk mendukung / bisa-lakukan dengan cepat jika tidak ada cara untuk membagi hal semacam ini.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.