1,052 bacaan
1,052 bacaan

Patutkah Anda Belajar Karat dan Zig? Ya, Ya Anda Harus

oleh Ace — The JS Hater9m2025/04/02
Read on Terminal Reader

Terlalu panjang; Untuk membaca

Nilai bahasa pemrograman yang tidak menyembunyikan butiran.
featured image - Patutkah Anda Belajar Karat dan Zig? Ya, Ya Anda Harus
Ace — The JS Hater HackerNoon profile picture

Bahasa yang Mendedahkan Butiran

Apabila kebanyakan orang memulakan pengaturcaraan, mereka tertarik kepada bahasa yang memudahkan urusan. Python, JavaScript dan bahasa peringkat tinggi yang lain mengasingkan butiran pengurusan memori, panggilan sistem dan interaksi perkakasan yang tidak kemas. Abstraksi ini berkuasa—ia membolehkan pemula mencipta program berguna dengan cepat tanpa terperangkap dalam butiran pelaksanaan.


Tetapi terdapat nilai penting dalam bahasa yang memaksa anda untuk menghadapi butiran ini. Bahasa seperti Rust, C dan Zig bukan sahaja menjadikan anda pengaturcara yang lebih baik dalam bahasa khusus tersebut—ia memperdalam pemahaman anda tentang cara komputer sebenarnya berfungsi. Pemahaman ini menjadikan anda lebih berkesan dalam setiap bahasa yang anda gunakan, walaupun bahasa peringkat tinggi.


Untuk menunjukkan, mari kita ambil konsep "mudah" seperti membaca input daripada pengguna dan menyimpannya dalam pembolehubah, kemudian menunjukkan cara ia akan dilakukan daripada bahasa peringkat tinggi ke rendah. Kami akan mulakan dengan yang paling tinggi daripada kesemuanya:

Ular sawa

 name = input("What is your name?\n") print(name) #Ah, the classic I/O example


Kepada pelajar, apakah soalan dan pembelajaran di sini? Ingat, kami bukan sahaja cuba mengeluarkan kod, tetapi sebenarnya mempunyai idea tentang perkara yang sedang berlaku:


  • Pembolehubah dan Memori: Kami mempunyai "pembolehubah" yang menyimpan data.

  • Jenis Data dan Memori: Kami mempunyai jenis data, dan rentetan hanyalah teks biasa. Pelajar yang sangat ingin tahu malah boleh belajar tentang jenis data lain daripada petunjuk ini.

  • Panggilan Fungsi: Kita boleh memanggil fungsi dengan argumen dan menyimpan hasil fungsi tersebut dalam pembolehubah.

  • Program Python Persekitaran Runtime boleh dijalankan dengan memanggil jurubahasa dan dengan atur cara (dengan andaian kami telah memasang Python; saya tidak akan mencucuk beruang yang merupakan versi Python, kebergantungan dan pemasangan). Ini boleh membawa kepada penemuan tentang bahasa yang ditafsir vs yang disusun.


Ini tidak buruk; Saya rasa pengetahuan terbesar tentang komputer akan datang daripada '\n' kecil itu dalam rentetan. Meneroka sedikit tentang perkara ini akan membawa kepada pengetahuan tentang ASCII, UTF-8, dan perwakilan teks dalam komputer sebagai bait. Ia mungkin terlalu banyak untuk pemula, tetapi ia akan memberi mereka idea tentang cara teks pergi ke 0s dan 1s. Terdapat juga sedikit pengajaran tentang jurubahasa dan penyusun di sini, tetapi itu memerlukan penggalian yang ketara.

Javascript/Typescript (Nod)

 import readline from 'readline/promises'; const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const name = await rl.question('What is your name?\n'); rl.close(); console.log(name); //Oh, js, so horribly wonderful in your ways


Sebagai tambahan kepada cerapan sebelumnya, mari kita menilai perkara yang boleh diperhatikan oleh pelajar yang ingin tahu daripada hanya meneroka kod ini:


  • Aliran Input/Output : Kami melihat rujukan eksplisit kepada stdin dan stdout. Penerokaan mudah ini akan membawa kepada aliran fail stdin dan stdout dalam persekitaran berasaskan Unix, dan mungkin juga deskriptor fail dan 'semuanya adalah fail' dalam sistem Linux.


  • Proses: Melihat objek Proses boleh mencetuskan orang yang ingin tahu untuk mengetahui tentang proses dan mendapatkan gambaran tentang proses pelaksanaan untuk sistem pengendalian moden. Walaupun mereka mungkin tidak memahaminya sepenuhnya, mereka kini mempunyai idea.


  • I/O Asynchronous : await and Promises memperkenalkan pelajar kepada cara komputer mengendalikan operasi yang tidak selesai serta-merta, dan mungkin juga soalan mengapa ia tidak hanya dilaksanakan dengan cara yang mudah (seperti Python). Ini mendorong untuk belajar tentang:


    • Pelaksanaan segerak dan tak segerak, I/O tidak menyekat, dan mungkin serentak

    • Promises, Microtask Queue dan Task Queue dalam Node, pengaturcaraan dipacu peristiwa dan faedahnya.


  • Penciptaan Antara Muka dan Pengurusan Sumber: Penciptaan dan penutupan antara muka membawa seseorang kepada persoalan dan memperoleh pemahaman tentang pengurusan sumber, terutamanya untuk sumber penting seperti aliran I/O.


  • Kata Kunci Perisytiharan ( let , const ): Ini tidak memetakan secara eksplisit kepada konsep yang lebih mendalam, tetapi ia mengajar amalan baik untuk mengawal kebolehubahan.


  • Persekitaran Masa Jalan: Program JS dijalankan melalui masa jalan, Node, Bun, Deno, dll. Tugas masa jalan adalah untuk menyediakan V8 (enjin JS) dengan ciri tambahan untuk menjadikannya bahasa yang lengkap. Seseorang mungkin boleh mempersoalkan apa sebenarnya masa jalan ini memberikan kepada enjin V8, dan ini akan membawa kepada pelaksanaan I/O async.


Sebahagian daripada ini, seperti Promises and Queues, adalah abstraksi berkaitan JS pada pandangan pertama, tetapi jika seseorang akhirnya menemui jalan mereka ke Libuv — perpustakaan C yang mengendalikan I/O tak segerak untuk Node.js - mereka akan belajar sedikit tentang I/O dalam sistem pengendalian.

C-Sharp

 Console.WriteLine("What is your name?"); string? name = Console.ReadLine(); Console.WriteLine(name); //Surprise!! No public static void Main(string[] args)


Suspek biasa pengekodan aksara ada di sini, walaupun dikaburkan oleh ReadLine dan WriteLine , selain itu, dua perkara penting muncul:


  • Penaipan Statik dan Jenis Eksplisit : Walaupun inferens jenis adalah ciri yang menarik untuk produktiviti, saya mengekalkan pandangan bahawa menulis jenis secara eksplisit meningkatkan proses pembelajaran, terutamanya untuk pemula. Di sini, pelajar boleh memperoleh idea sebenar pertama mereka tentang susun atur memori, terutamanya semasa mereka meneroka sebab untuk menyatakan secara eksplisit jenis pembolehubah. Ini termasuk tempahan kiraan bait tertentu untuk pembolehubah tertentu dan ralat yang berlaku apabila anda cuba memasukkan 64 bait ke dalam 32 bait memori.


  • Jenis Boleh Nullable: Mereka mengetahui bahawa adalah mungkin untuk lokasi memori mempunyai ketiadaan nilai yang sah, meningkatkan lagi pandangan ingatan.


  • Orang yang benar-benar ingin tahu akan mula bertanya — Mengapa kita perlu menyatakan jenis boleh batal secara eksplisit? Adakah terdapat sebarang isu tertentu yang berpunca daripada menganggap nilai nol sebagai nilai bukan nol dalam program? Ini membawa kepada pembelajaran tentang peraturan perlindungan memori.


  • Common Language Runtime(CLR), Intermediate Language(IL) dan JIT: The .NET runtime menjadikan proses kompilasi lebih jelas dengan memaksa pelajar membina secara eksplisit dan kemudian menjalankan kod.


Memaksa pengguna untuk menyusun kod mereka membolehkan mereka melihat IL yang dijana. Ini membolehkan kita melihat pertama kita ke dalam pemasangan(pseudo-assembly, anyway), arahan, dan daftar. Terdapat juga potensi untuk belajar tentang kompilasi Just-In-Time CLR jika pelajar mencucuk sedikit lebih jauh di bawah tudung.


Walaupun konsep-konsep ini wujud dalam bahasa lain, perbezaannya ialah mendedahkannya kepada pengguna membolehkan mereka segera mencucuk lebih dalam dan mendapatkan idea tentang apa yang sebenarnya berlaku untuk menjalankan kod tersebut.


Akhirnya, I/O Lebih Abstrak Di Sini berbanding JS. Kami tidak mempunyai apa-apa yang berkaitan dengan aliran dan pengurusan sumber.

Golang

Maaf, Gophers, tetapi saya tidak dapat membincangkan semuanya, atau artikel ini akan menjadi terlalu panjang.

karat

 use std::io; fn main() { println!("What is your name?"); let mut name = String::new(); io::stdin() .read_line(&mut name) .expect("Failed to read line"); println!("{}", name); } //Almost a 1:1 from The Book


Kepada pelajar yang agak ingin tahu, apa yang boleh difahami tentang konsep sistem:


  • Kebolehubahan Eksplisit : kata kunci mut menunjukkan pembolehubah tidak boleh diubah secara lalai. Sekali lagi, kawal kebolehubahan data untuk semua faedahnya.


  • Pengendalian Ralat Eksplisit : .expect() menunjukkan bahawa I/O boleh gagal dan memaksa pertimbangan pengendalian ralat. Ini hampir dipandang remeh dalam bahasa yang lebih tinggi, dan pelajar boleh memahami bahawa berinteraksi dengan peranti fizikal boleh membawa kepada pelbagai ralat yang mungkin tidak difikirkan jika ia tidak dibawa ke hadapan. Sebagai contoh, cuba tanya pembangun pangkalan data jika cakera adalah sempurna.


  • Akses Strim Langsung : io::stdin() secara eksplisit mendedahkan interaksi dengan sumber I/O peringkat OS. Sama seperti sebelum ini, ini membolehkan untuk menyelam lebih mendalam ke dalam konsep I/O dalam OS, perbezaan di sini ialah perkara-perkara yang jauh lebih terdedah berbanding dalam JS.


  • Peruntukan Memori : String::new() menunjukkan pertemuan pertama kami, walaupun pseudo-eksplisit, dengan timbunan dan timbunan, dua daripada konsep paling penting dalam ingatan. Walaupun tidak begitu eksplisit, ia memberikan petunjuk yang cukup bahawa pelajar yang ingin tahu mungkin mula meneroka ingatan dengan mudah dan bertanya soalan seperti - "Mengapa kita memerlukan kawasan memori yang berbeza?" “apa timbunan itu?” dll.


  • Rujukan & Pinjaman : &mut name mendedahkan pengenalan eksplisit pertama kami kepada penunjuk . Walaupun setiap bahasa setakat ini telah menggunakan rujukan di bawah hud, mendedahkannya di hadapan-dan-tengah kepada pengaturcara membolehkan mereka mula memperoleh idea yang lebih mendalam tentang susun atur memori. Mereka mengetahui bahawa kita boleh menggunakan data yang sama di berbilang wilayah dengan hanya menggunakan rujukan, bersama-sama dengan faedah dan bahaya pendekatan sedemikian.


  • Penyusun, Boleh Laksana dan Perhimpunan: Sekali lagi, memerlukan langkah binaan secara eksplisit menyebabkan pelajar mula meneroka proses penyusunan, tetapi kali ini, mereka berpeluang melihat penerokaan sehingga titik arahan pemasangan dan sedikit tentang proses pelaksanaan CPU moden.


Walaupun anda selesa dengan abstraksi peringkat tinggi, bereksperimen dengan satu elemen kecil dalam Rust boleh menerangi seluruh dunia tingkah laku sistem yang kekal tersembunyi dalam bahasa lain. Kebanyakannya bukan perkara baru, jadi untuk mengatakan, perbezaannya ialah di sini, mereka terdedah kepada pengaturcara, memaksa mereka untuk berfikir dan belajar tentang mereka. Ini memang membawa overhed dan kesukaran tambahan, tetapi ini diberi ganjaran oleh pemahaman yang lebih mendalam, dan akibatnya, kuasa ke atas sumber sistem.

Zig

 const std = @import("std"); pub fn main() !void { var debugAllocator = std.heap.DebugAllocator(.{}).init; defer std.debug.assert(debugAllocator.deinit() == .ok); const allocator = debugAllocator.allocator(); const stdout = std.io.getStdOut().writer(); const stdin = std.io.getStdIn().reader(); var name = std.ArrayList(u8).init(allocator); defer name.deinit(); try stdout.print("What is your name?\n", .{}); try stdin.streamUntilDelimiter(name.writer(), '\n', null); try stdout.print("{s}\n", .{name.items}); } //lol, the code block doesn't have support for Zig


NOTA: Saya benar-benar berdebat sama ada untuk memasukkan rentetan 'boleh berkembang' yang diperuntukkan timbunan atau hanya mempunyai rentetan 'statik' yang diperuntukkan secara tindanan yang sangat besar, tetapi kerana saya telah menggunakan rentetan 'boleh berkembang' untuk setiap contoh lain, inilah kita. Untuk menerangkan secara ringkas, rentetan boleh tumbuh boleh berkembang dengan input tambahan, manakala rentetan statik ditetapkan — satu-satunya cara untuk menambah aksara baharu ialah mencipta aksara baharu dengan aksara baharu.


Oh budak, di mana kita bermula? Jika pelajar melihat kod ini, mereka mungkin akan takut dan melarikan diri, tetapi apa yang boleh dipelajari tentang konsep sistem dengan meneroka ini:


  • Peruntukan dan Ingatan: Zig menjelaskan kepada kita bahawa apabila kita perlu mendapatkan ingatan daripada timbunan, kita perlu mengisytiharkan niat kita untuk berbuat demikian; ini tidak begitu abstrak untuk kami seperti dalam Rust. Di sini, ia terdedah. Walaupun ini menambah lebih banyak overhed awal, ia menggesa pembangun untuk mula meneroka tindanan, timbunan, memori dinamik, syscalls OS dan sebab kami perlu memperuntukkan dan membebaskan memori secara eksplisit. Ini mengukuhkan lagi pemahaman pembangun tentang struktur memori.


  • Pengesanan Pembersihan dan Kebocoran: Panggilan defer eksplisit untuk membersihkan memori dan pemeriksaan untuk kebocoran memori adalah titik permulaan yang baik untuk mempelajari secara langsung isu yang timbul daripada ingatan yang tidak diurus dengan betul. Pada ketika ini, pembangun sudah cukup lengkap untuk mendalami topik ini.


  • Rentetan, Hirisan dan Rujukan: Rentetan hanyalah penunjuk kepada tatasusunan nilai u8 . Ini mengalih keluar sedikit abstraksi terakhir antara konsep 'rentetan' peringkat tinggi dan idea 'tatasusunan bait' peringkat rendah.


  • Akses Terus kepada Strim I/O: Sekali lagi, dengan membuat perkara ini kelihatan, pembangun memahami perkara yang berlaku apabila mereka membaca atau menulis daripada I/O di luar program.


  • Ralat I/O dan Pengendalian Ralat: Panggilan peranti I/O — dan syscalls, secara umum — boleh gagal. Pembangun perlu meneroka dan menyedari perkara ini.

C dan C++

Saya rasa anda faham maksud yang saya sampaikan di sini; tidak perlu mengalahkan kuda mati.


Jadi, begitulah. Tugas mudah dalam pelbagai bahasa. Saya harap anda telah yakin dengan pendapat saya. Namun, sebelum kita pergi, mari kita jelaskan beberapa perkara:

Jadi, Hanya Tulis Tulis Semula Dalam Karat?

Tidak, jawapannya adalah tidak - hanya tidak. Saya membuat hujah-hujah ini dari perspektif seseorang yang ingin mengetahui lebih lanjut tentang cara komputer berfungsi dan orang yang perlu memerah segala-galanya daripada perkakasan anda (anda juga boleh pergi perhimpunan, seperti lelaki di FFMPEG untuk itu, jika anda mahu).


Tetapi apa yang berlaku apabila anda baik-baik saja dengan mengorbankan sedikit kecekapan demi kelajuan pembangunan? Bagaimana jika anda perlu menulis pelayan web yang ringan dengan sedikit logik dalam satu atau dua hari? Apakah yang berlaku apabila anda seorang pembangun baharu yang sangat takut dengan C++ sehingga mereka mahu menggugurkan kod?


Terdapat banyak situasi di luar sana yang mana sesuatu seperti Go, Elixir, Haskell, atau apa sahaja yang baik-baik saja. Saya hanya meminta bahawa selepas itu, anda mengambil sedikit masa dan belajar sedikit tentang apa yang sebenarnya berlaku; anda tidak perlu menjadi ahli peringkat rendah yang boleh menulis asm dalam tidur mereka, tetapi mengetahui perkara yang berlaku dengan komputer akan membantu anda menulis kod yang lebih baik dan lebih berprestasi . Dan ini akan membantu anda berhenti melihat komputer anda sebagai kotak hitam. Saya juga berjanji anda akan menikmatinya.


Bercakap dengan saya di Twitter .

L O A D I N G
. . . comments & more!

About Author

Ace — The JS Hater HackerNoon profile picture
Ace — The JS Hater@ace2489
Software dev | Web3 with Rust/Solidity | Systems dev with Rust/Zig. Reach me at [email protected]

GANTUNG TANDA

ARTIKEL INI DIBENTANGKAN DALAM...

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks