Přijde mi škoda, že nevznikl programovací jazyk speciálně pro Linux.
Takový jazyk by mohl opravit hlavní problémy C a nepřidávat hromadu vlastních problémů jako Rust (kde hlavní problém je, že psaní unsafe kódu je ještě těžší než v C a bohužel bez unsafe kódu v Rustu nejde napsat ani základní datové struktury).
BTW dřív by mi přišlo šílené psát vlastní jazyk, ale dnes, když se podívám na Zig, Odin, C3, Jai, Nim, Cone, cppfront, tak vidím, že to je reálné a stačí malý tým nebo dokonce jeden člověk.
A proc by mel byt programovaci jazyk svazany s jednim konkretnim operacnim systemem? Vzdyt to je tak nejak blbost.
Vyvoj jazyka se muze ridit potrebami projektu.
A proc by nekdo probuh chtel psat unsafe kod?
Protoze vyjadrovaci schopnosti v Rustu jsou velice omezene bez unsafe kodu.
Nedelate neco spatne, kdyz neco takoveho potrebujete?
To reknete tem, co napsali standardni knihovnu Rustu.
Konkretnim prikladem datove struktury je treba B-strom, ktery se v Rustu pouziva pro implementaci BTreeMap a BTreeSet.
Stromova struktura je implementovana v souboru node.rs. Par poznamek k tomu:
(1) Podivejte se, kolikrat je pouzito klicove slovo unsafe. V soucasne implementaci je to vice nez 100 krat. Momentalne je tam 1873 radku kodu s komentari, takze unsafe pripada zhruba na kazdych 18 radku kodu.
(2) Bohuzel i funkce, ktere jsou zvenku safe mohou totalne pokazit invarianty, na ktere kompilator spoleha. Napr.
/// Note that, despite being safe, calling this function can have the side effect
/// of invalidating mutable references that unsafe code has created.
pub(super) fn len(&self) -> usize {
// Crucially, we only access the `len` field here. If BorrowType is marker::ValMut,
// there might be outstanding mutable references to values that we must not invalidate.
unsafe { usize::from((*Self::as_leaf_ptr(self)).len) }
}
(3) Bohuzel invarianty, na ktere kompilator Rustu spoleha, je tezke kontrolovat, tezsi nez u C nebo C++. Zejmena mam na mysli invariant, ze pokud existuje mutable reference, tak nesmi existovat zadna jina reference. Pozor, jedna se o existenci. To je jeden z duvodu, proc se v Rustu pouzivaji unsafe ukazatele - ty totiz nemaji zadne omezeni. Problem ale nastane v okamziku, kdy ukazatel pretypujete na referenci a porusite ten invariant, ze existuje nejvyse jedna mutable reference.
(4) Velka cast kodu v node.rs se zabyva jen tim, jak manipulovat s datovou strukturou, aniz by se nejaky invariant porusil. Kdyz byste to prepsal do C, tak vam cca 1/3 kodu odpadne.
(5) V tomhle kodu je navic vtipne, ze se tam pouzivaji triky z C. Konkretne se jedna o pretypovavani ukazatelu LeafNode na ukazatele InternalNode. Coz je legalni diky repr(C), ktere garantuje urcity layout v pameti:
#[repr(C)]
// gdb_providers.py uses this type name for introspection.
struct InternalNode<K, V> {
data: LeafNode<K, V>,
(6) Takhle je napsana znacna cast standardni knihovny. A protoze verim, ze lide, co napsali standardni knihovnu, umi Rust, tak z toho usuzuji, ze to asi nejde napsat lepe.
> Bohuzel invarianty, na ktere kompilator Rustu spoleha, je tezke kontrolovat, tezsi nez u C nebo C++.
Jak to může být těžší, když C a C++ tyhle možné problémy zcela ignoruje? Naopak je potřeba kontrolovat konstantně všecho, což to dělá mnohem náročnější.
Ano, některé konstrukce je těžké psát bez unsafe, protože je těžké psát to safe, nezávisle na jazyku :)
Jak to může být těžší, když C a C++ tyhle možné problémy zcela ignoruje?
V C i C++ je situace jednodušší, protože pokud nepoužíváte klíčové slovo restrict, tak kompilátor musí předpokládat aliasing u ukazatelů na stejný typ.
Takže v C nebo C++ mohu mít více ukazatelů či referencí na jednu hodnotu. Zatímco v Rustu tohle s &mut referencemi nejde, resp. jde, ale je to nedefinované chování. A těžko se to hledá viz. ten komentář, co mají u len.
> Takže v C nebo C++ mohu mít více ukazatelů či referencí na jednu hodnotu.
A moje pointa je, že kód který tohle dělá má potenciálně problémy, které je potřeba neustále hlídat. To že není možné mít v safe kódu víc mutable referencí najednou má dobrý důvod, pokud to dělám v C, musím si manuálně hlídat kde mám víc mutable referencí a zajistit že jsou sound. Je to stejně komplikované, jen to můžu snáz ignorovat a je snazší přehlédnout to.
Předpokládám že tou základní datovou strukturou myslíš LinkedList a příbuzné konstrukce, protože to je nejčastější stížnost na Rust. Ono to nejde efektivně napsat bez unsafe z jednoho prostého důvodu: Napsat LinkedList tak aby byl sound je relativně složitá věc. Jazyky které nejsou memory safe tu komplexitu dovolují nevidět.
(Navíc, drtivá většina využití takových struktur je špatně, jedna z mála výjimek je třeba psaní vlastního alokátoru. Ve většině případů bude Vec výkonnější než LinkedList, i při náhodném odebírání a přidávání prvků uprostřed)
Není důvod myslet si, že by jazyk speciálně pro Linux netrpěl stejnými problémy, pokud by měl mít stejné schopnosti.
31. 1. 2025, 11:58 editováno autorem komentáře