1,052 čítania
1,052 čítania

Mali by ste sa naučiť Rust a Zig?Áno, Áno, mali by ste

podľa Ace — The JS Hater9m2025/04/02
Read on Terminal Reader

Príliš dlho; Čítať

Hodnota programovacích jazykov, ktoré neskrývajú detaily.
featured image - Mali by ste sa naučiť Rust a Zig?Áno, Áno, mali by ste
Ace — The JS Hater HackerNoon profile picture

Jazyky, ktoré odhaľujú podrobnosti

Keď väčšina ľudí začína s programovaním, priťahujú ich jazyky, ktoré uľahčujú prácu. Python, JavaScript a ďalšie jazyky na vysokej úrovni odstraňujú chaotické detaily správy pamäte, systémových volaní a interakcie hardvéru. Táto abstrakcia je výkonná – umožňuje začiatočníkom rýchlo vytvárať užitočné programy bez toho, aby sa zamotali do detailov implementácie.


Jazyky, ktoré vás nútia konfrontovať sa s týmito detailmi, však majú významnú hodnotu. Jazyky ako Rust, C a Zig z vás nerobia len lepšieho programátora v týchto špecifických jazykoch – prehlbujú vaše pochopenie toho, ako počítače skutočne fungujú. Vďaka tomuto porozumeniu budete efektívnejší v každom jazyku, ktorý používate, dokonca aj v tých na vysokej úrovni.


Aby sme to demonštrovali, zoberme si „jednoduchý“ koncept, ako je čítanie vstupu od používateľa a jeho uloženie do premennej, potom ukážme, ako by sa to dalo urobiť z jazykov vyššej úrovne na úroveň nižšej. Začneme tým najvyšším zo všetkých:

Python

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


Aké otázky tu môžu byť pre študenta? Pamätajte, že sa nesnažíme len vylúštiť kód, ale máme skutočne predstavu o tom, čo sa deje:


  • Premenné a pamäť: Máme „premenné“, ktoré uchovávajú údaje.

  • Dátové typy a pamäť: Máme dátové typy a reťazce sú jednoducho normálny text. Veľmi zvedavý študent by sa z tejto stopy mohol dozvedieť aj o iných typoch údajov.

  • Volania funkcií: Môžeme volať funkcie s argumentmi a uložiť výsledky týchto funkcií do premennej.

  • Runtime Environment Python programy môžu byť spustené volaním interpreta a s programom (za predpokladu, že máme nainštalovaný Python; nebudem pykať za verzie, závislosti a inštaláciu Pythonu). To by mohlo viesť k objavu interpretovaných a kompilovaných jazykov.


Tieto nie sú zlé; Myslím, že najväčšie znalosti o počítačoch budú pochádzať z toho malého „\n“ v reťazci. Trocha preskúmania by viedlo k znalostiam o ASCII, UTF-8 a reprezentácii textu v počítači ako bajtov. Pre začiatočníka by to bolo asi priveľa , ale dalo by to predstavu o tom, ako ide text na 0 a 1. Je tu tiež malá lekcia o interpretoch a kompilátoroch, ale to by si vyžadovalo značné hĺbanie.

Javascript/Typescript (Uzol)

 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


Okrem predchádzajúcich poznatkov zhodnoťme, čo by zvedavý študent mohol pozorovať jednoduchým skúmaním tohto kódu:


  • Vstupné/výstupné toky : Vidíme explicitné odkazy na štandardné a štandardné parametre. Ich jednoduché preskúmanie by viedlo k prúdom súborov stdin a stdout v prostrediach založených na Unixe a možno dokonca aj k deskriptorom súborov a „všetko je súbor“ v systémoch Linux.


  • Procesy: Videnie objektu Process by mohlo zvedavého človeka podnietiť k tomu, aby sa dozvedel o procesoch a nahliadol do procesu vykonávania moderných operačných systémov. Aj keď to nemusia úplne pochopiť, teraz majú nápad.


  • Asynchrónne I/O : await a Promises oboznamujú študenta s tým, ako počítače zvládajú operácie, ktoré sa nedokončia okamžite, a možno aj s otázkou, prečo sa to jednoducho nevykonáva priamočiarym spôsobom (ako Python). Tieto motivujú k učeniu sa o:


    • Synchrónne a asynchrónne vykonávanie, neblokujúce I/O a možno aj súbežnosť

    • Promises, Microtask Queue a Task Queue v Node, programovanie riadené udalosťami a jeho výhody.


  • Vytvorenie rozhrania a správa zdrojov: Vytvorenie a zatvorenie rozhrania vedie k otázke a získaniu pochopenia správy zdrojov, najmä pre dôležité zdroje, ako sú I/O toky.


  • Kľúčové slová deklarácie ( let , const ): Tieto sa explicitne netýkajú hlbších konceptov, ale učia osvedčené postupy kontroly premenlivosti.


  • Runtime prostredie: JS programy sa spúšťajú cez runtime, Node, Bun, Deno, atď. Úlohou runtime je poskytnúť V8 (JS engine) ďalšie funkcie, aby sa z neho stal kompletný jazyk. Možno by sa dalo položiť otázku, čo presne tieto runtime poskytujú motoru V8, a to by viedlo k implementácii asynchrónnych I/O.


Niektoré z nich, ako Promises a Queues, sú na prvý pohľad abstrakcie súvisiace s JS, ale ak si človek nakoniec nájde cestu do Libuv – knižnice C, ktorá spracováva asynchrónne I/O pre Node.js – naučí sa niečo o I/O v operačných systémoch.

C-Sharp

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


Zvyčajní podozriví z kódovania znakov sú tu, aj keď sú zakrytí ReadLine a WriteLine , okrem toho sa objavia dve dôležité veci:


  • Statické písanie a explicitné typy : Aj keď je odvodzovanie typu skvelou funkciou pre produktivitu, zastávam názor, že explicitné písanie typov zlepšuje proces učenia, najmä pre začiatočníkov. Tu by študent mohol získať svoju prvú skutočnú predstavu o rozložení pamäte, najmä keď skúmal dôvody pre explicitné špecifikovanie typov premenných. Patrí medzi ne rezervácia špecifických počtov bajtov pre určité premenné a chyby, ktoré sa vyskytnú, keď sa pokúsite vložiť 64 bajtov do 32 bajtov pamäte.


  • Typy s nulovou hodnotou: Učia sa, že je možné, že miesto v pamäti nemá platnú hodnotu, čo ďalej zlepšuje pohľad na pamäť.


  • Naozaj zvedavý človek by sa začal pýtať — Prečo musíme explicitne uvádzať typy s nulovou hodnotou? Existujú nejaké konkrétne problémy, ktoré vyplývajú z toho, že v programoch sa s nulovými hodnotami zaobchádza ako s nenulovými hodnotami? To vedie k učeniu sa o pravidlách ochrany pamäte.


  • Common Language Runtime (CLR), Intermediate Language (IL) a JIT: Runtime .NET robí proces kompilácie zrejmejším tým, že núti študenta explicitne zostaviť a potom spustiť kód.


Nútenie používateľa skompilovať svoj kód mu umožňuje vidieť vygenerovaný IL. To nám umožňuje náš prvý pohľad do zostavy (v každom prípade pseudozostava), pokynov a registrov. Existuje tiež potenciál dozvedieť sa o Just-In-Time kompilácii CLR, ak študent načrie trochu ďalej pod kapotu.


Aj keď tieto koncepty existujú v iných jazykoch, rozdiel je v tom, že ich odhalenie používateľovi im umožňuje okamžite preniknúť hlbšie a získať predstavu o tom, čo sa skutočne stane pri spustení kódu.


Nakoniec, I/O je tu viac abstraktné ako v JS. Nemáme nič, čo by sa týkalo streamov a správy zdrojov.

Golang

Prepáčte, Gophers, ale nemôžem pokryť všetko, inak by bol tento článok príliš dlhý.

Hrdza

 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


Pre mierne zvedavého študenta, čo možno pochopiť o systémových konceptoch:


  • Explicitná mutabilita : kľúčové slovo mut ukazuje, že premenné sú štandardne nemenné. Opäť kontrola nad premenlivosťou údajov pre všetky jej výhody.


  • Explicitné spracovanie chýb : .expect() ukazuje, že I/O môže zlyhať a núti zvážiť spracovanie chýb. Vo vyšších jazykoch sa to takmer považuje za samozrejmosť a študent môže pochopiť, že interakcia s fyzickými zariadeniami môže viesť k množstvu chýb, o ktorých by sa nemuselo ani zamýšľať, ak by neboli predložené. Skúste sa napríklad opýtať vývojára databázy, či sú disky dokonalé.


  • Direct Stream Access : io::stdin() explicitne odhaľuje interakciu s I/O zdrojmi na úrovni OS. Rovnako ako predtým to umožňuje hlbší ponor do konceptov I/O v operačnom systéme, pričom rozdiel je v tom, že veci sú oveľa holé ako v JS.


  • Memory Allocation : String::new() ukazuje naše prvé, aj keď pseudoexplicitné, stretnutie s haldou a zásobníkom, dvoma z najdôležitejších pojmov v pamäti. Aj keď to nie je príliš explicitné, poskytuje dostatok informácií, že zvedavý študent môže ľahko začať skúmať pamäť a klásť otázky ako: „Prečo potrebujeme rôzne pamäťové oblasti? "Čo je to hromada?" atď.


  • Referencie a pôžičky : &mut name odhaľuje náš prvý explicitný úvod do ukazovateľov . Hoci každý jazyk doteraz používal pod kapotou referencie, ich vystavenie programátorom vpredu a v strede im umožňuje začať získavať hlbšie predstavy o rozložení pamäte. Učia sa, že môžeme použiť rovnaké údaje vo viacerých regiónoch jednoduchým použitím referencií spolu s výhodami a nebezpečenstvom takéhoto prístupu.


  • Kompilátory, spustiteľné súbory a zostavenie: Výslovné vyžadovanie kroku zostavenia opäť spôsobí, že študent začne skúmať proces kompilácie, ale tentoraz má možnosť vidieť preskúmať až do bodu montážnych pokynov a trochu o procese vykonávania moderných CPU.


Aj keď vám vyhovuje abstrakcia na vysokej úrovni, experimentovanie s jedným malým prvkom v Ruste môže osvetliť celý svet správania systému, ktorý zostáva skrytý v iných jazykoch. Väčšina z nich nie je nová, rozdiel je v tom, že tu sú vystavení programátorovi, čo ich núti premýšľať a učiť sa o nich. Prináša to dodatočnú réžiu a ťažkosti, ale to je odmenené hlbším porozumením a následne mocou nad zdrojmi systému.

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


POZNÁMKA: Naozaj som diskutoval o tom, či zahrnúť alebo nezahrnúť haldy pridelené „rastúce“ reťazce alebo jednoducho mať veľmi veľký „statický“ reťazec pridelený zásobníkom, ale keďže som použil „rastúteľné“ reťazce pre každý ďalší príklad, tu sme. Jednoducho povedané, rastúci reťazec môže rásť s dodatočným vstupom, zatiaľ čo statický reťazec je pevný – jediný spôsob, ako pridať nové znaky, je vytvoriť nový s novým znakom.


Ach chlapče, kde začneme? Ak by sa študent pozrel na tento kód, pravdepodobne by sa zľakol a utiekol, ale čo by sa mohol dozvedieť o systémových konceptoch, keď si preštuduje toto:


  • Alokátory a pamäť: Zig nám jasne hovorí, že keď potrebujeme získať pamäť z hromady, musíme deklarovať svoj zámer tak urobiť; nie je to pre nás také abstrahované ako v Rust. Tu je to odhalené. Aj keď to zvyšuje počiatočnú réžiu, vyzve vývojára, aby začal skúmať zásobník, haldu, dynamickú pamäť, systémové volania OS a prečo dokonca potrebujeme explicitne alokovať a uvoľniť pamäť. To ďalej posilňuje vývojárov pochopenie štruktúry pamäte.


  • Čistenie a detekcia úniku: Výslovné defer volaní na vyčistenie pamäte a kontroly úniku pamäte sú dobrými východiskovými bodmi na to, aby ste sa z prvej ruky dozvedeli o problémoch, ktoré vznikajú v dôsledku nesprávne spravovanej pamäte. V tejto chvíli je vývojár dostatočne vybavený na to, aby šiel v tejto téme naozaj do hĺbky.


  • Reťazec, rezy a referencie: Reťazce sú jednoducho ukazovatele na pole hodnôt u8 . Tým sa odstráni posledný kúsok abstrakcie medzi konceptom „reťazca“ na vysokej úrovni a myšlienkou „pola bajtov“ na nízkej úrovni.


  • Priamy prístup k vstupno-výstupným tokom: Zviditeľnením týchto vecí vývojár opäť chápe, čo sa stane, keď čítajú alebo zapisujú z I/O mimo programu.


  • Chyby I/O a spracovanie chýb: Volania I/O zariadení – a vo všeobecnosti systémové volania – môžu zlyhať. Vývojár to musí preskúmať a uvedomiť si to.

C a C++

Myslím, že ste pochopili pointu, ktorú tu chcem povedať; netreba biť mŕtveho koňa.


Takže tu máte. Jednoduchá úloha vo viacerých jazykoch. Dúfam, že ste boli presvedčení o mojom názore. Predtým, ako pôjdeme, si však ujasnime niekoľko vecí:

Takže, stačí to napísať a prepísať v hrdze?

Nie, odpoveď je nie – len nie. Tieto argumenty uvádzam z pohľadu toho, kto sa chce dozvedieť viac o tom, ako fungujú počítače, a toho, kto potrebuje vytlačiť všetko z vášho hardvéru (môžete ísť aj na montáž, ako na to chalani z FFMPEG , ak chcete).


Čo sa však stane, keď v záujme rýchlosti vývoja v pohode obetujete určitú efektivitu? Čo ak potrebujete napísať ľahký webový server s určitou logikou za deň alebo dva? Čo sa stane, keď ste nový vývojár, ktorý je tak zastrašený C++, že chce zahodiť kód?


Existuje veľa situácií, pre ktoré je niečo ako Go, Elixir, Haskell alebo čokoľvek iné. Len vás žiadam, aby ste si potom našli čas a dozvedeli sa trochu o tom, čo sa skutočne deje; nemusíte byť hlupák na nízkej úrovni, ktorý dokáže písať asm aj v spánku, ale vedieť, čo sa deje s počítačmi, vám pomôže napísať lepší a výkonnejší kód . A pomôže vám to prestať vnímať váš počítač ako čiernu skrinku. Tiež sľubujem, že si to užijete.


Porozprávajte sa so mnou na Twitteri .

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks