Portál AbcLinuxu, 30. dubna 2025 23:56
nectí zpětnou kompatibilituAle ctí, resp. nějaké nekompatibilní změny byly, ale typicky pouze v corner-casech nebo případně v kódu, který nebyl korektní... Jinak bod 1. je otázka názoru, 3. a 5. nechápu - C standard žádné ABI nespecifikuje. Jako relevantní mi přijdou body 4. a 6., upřesnil bych to ještě tím, že Rust má pouze (realisticky) jednu implementaci, která je postavená nad LLVM, což je problém.
Ad 1) říká: Když máte namísto C používat méně univerzální Rust, tak stejně budete muset na některé úlohy (které nezvládne Rust) použít to C. Ergo kladívko Rust nemůže nahradit a vykopnout C, ani kdyby se Rust rozkrájel.Rust je méně univerzální v tom, že podporuje méně platforem než C. Pokud ale danou platformu podporuje, moc nevidim, v čem je méně univerzální. Jinak celkem souhlasim, že Rust pravděpodobně nikdy úplně nenahradí C/C++, a vlastně ani nevim, proč by měl. Za mě úplně postačí, když bude existovat jako použitelná alternativa k C/C++ a bude mít nějaké slušné procento. Což si myslim, že je docela realistické... Nahradit veškerý C/C++ kód Rustem chtějí jen přiblblí fanatici nebo trollové, kteří typicky s nim ani nemají moc zkušeností...
"Nějaké nekompatibilní změny byly" - to je vše. Já mohu vzít 30 let staré zdrojové kódy v C, přeložit je na jakékoli platformě, a dělají přesně to samé co před 30 lety. Samozřejmě pokud si vystačím se standardem.Malá část reálně existujícího kódu si vystačí jen se standardem a/nebo je skutečně dobře napsaná podle standardu.
Ad 5) Standard C/C++ ABI nedefinuje. Ale protože je C/C++ základní a univerzální jazyk, tak obvykle každá platforma definuje nějaké ABI pro C. A na ní se můžete mnoha jazyky napojit.Tady nevidim žádnou pointu. V Rustu můžeš udělat to samé, co v C++ - exponovat C-kompatibilní API/ABI.
Jinak celkem souhlasim, že Rust pravděpodobně nikdy úplně nenahradí C/C++, a vlastně ani nevim, proč by měl. Za mě úplně postačí, když bude existovat jako použitelná alternativa k C/C++ a bude mít nějaké slušné procento.
Nevím, jestli je dobré mluvit o C a C++ jako o jednom jazyku (tzn. psát C/C++). Pokud se na C++ budeme dívat jako na vysokoúrovňový jazyk určený k psaní složitějších aplikací, tak by ho Rust (nebo třeba D) nahradit mohl, ne?
Problém je akorát v tom, že při psaní C++ aplikace můžeš kdykoli plynule přejít do C a používat přímo céčkové knihovny. Což je vlastnost, kterou prakticky žádný jiný jazyk nemá (snad leda D).
Jak se to liší od nativních funkcí (případně JNA) v Javě?
Ano a z C nebo C++ můžu volat kód psaný v Javě. Nicméně v obou těch směrech je to diametrálně odlišné od toho, jak se integruje C a C++, protože tam je to naprosto bezešvé, je to jeden jazyk (C jako podmnožina C++). Částečně se tomu blíží D, ale jinak nevím o jiném jazyku, který by se tak dobře integroval s C nebo dokonce C++.
Nevím, jestli je dobré mluvit o C a C++ jako o jednom jazyku (tzn. psát C/C++). Pokud se na C++ budeme dívat jako na vysokoúrovňový jazyk určený k psaní složitějších aplikací, tak by ho Rust (nebo třeba D) nahradit mohl, ne?Jj, když píšu C/C++, myslim tím spíš C, C++; jsou to dva dost různé jazyky. Rust, D, atd. by C++ teoreticky nahradit mohly, v praxi v C++ je napsáno obrovské množství kódu, takže to by trvalo dlouho, jestli se to vůbec někdy stane (IMO spíš ne). Taky se může stát, že C++ nebo D přidaj borrow-checker a pak by to mohlo vypadat jinak. Walter Bright už trochu vyměkl a možná něco takového přidá. (Osobně ale moc nevěřim v úspěch D kvůli fragmentaci. Potřebovali by to spíš nějak defragmentovat
Problém je akorát v tom, že při psaní C++ aplikace můžeš kdykoli plynule přejít do C a používat přímo céčkové knihovny. Což je vlastnost, kterou prakticky žádný jiný jazyk nemá (snad leda D).V kontextu Rustu by tohle nebyla moc výhra, což je asi taky důvod, proč pro to není moc přímá podpora. Udělat binding pro C ve smyslu Rustového ekvivalentu header file je snadné a skoro úplně automatizovatelné, nicméně to gro těch bindingů je ve vytvoření idiomatického a hlanvě bezpečnost-zachovávajícího API, což je něco, co se obecně moc automatizovat nedá. (Ale na druhou stranu lidi to motivuje k tvorbě takových bindingů a existuje jich překvapivě relativně dost.)
Nevím, jestli je dobré mluvit o C a C++ jako o jednom jazyku (tzn. psát C/C++).Ale on to v zásadě jeden jazyk je. Dobře napsaný C kód je zároveň přeložitelným C++ kódem. Klidně se dá C++ považovat za vyšší verzi C. ---
Pokud se na C++ budeme dívat jako na vysokoúrovňový jazyk určený k psaní složitějších aplikací, tak by ho Rust (nebo třeba D) nahradit mohl, ne?Nemohl. Protože D i Rustu chybí v první řadě serióznost. a) C++ má vlastní standard, množství nezávislých kompilátorů. b) C++ má tu vlastnost, že C++ je stejně univerzální jako C, tj. napíšete v něm třeba operační systém, ovladače hw, můžete v něm psát kódy pro mikrokontrolery, atd. atd. atd. Aby mohl nějaký jazyk převálcovat C/C++, musí umět to samé plus ještě mnohem více, být stejně univerzální, mít seriózní standard. A hlavně: Musí mít nějakou killer feature, která způsobí, že se vyplatí opustil C/C++ a přejít na ten nový super jazyk, který je převálcuje. ---
Jj, když píšu C/C++, myslim tím spíš C, C++; jsou to dva dost různé jazyky. Rust, D, atd. by C++ teoreticky nahradit mohly, v praxi v C++ je napsáno obrovské množství kódu, takže to by trvalo dlouho, jestli se to vůbec někdy stane (IMO spíš ne).Ale C/C++ je v zásadě stejný jazyk. Mají stejnou syntaxi, stejnou knihovnu, ... Jen C++ toho má trochu více. C++ je jediný jazyk, který má našlápnuto na to smést C z povrchu zemského. Žádný jiný dnešní programovací jazyk C nenahradí. ---
Taky se může stát, že C++ nebo D přidaj borrow-checker a pak by to mohlo vypadat jinak. ... Osobně ale moc nevěřim v úspěch D kvůli fragmentaci. Potřebovali by to spíš nějak defragmentovat.D má mnohem více problémů než jen defragmentaci. Je zvláštní, že tvůrci jazyků podceňují právě ty drobnosti, co rozhodují nejvíce o úspěchu jazyka: serióznost, dobře psaný standard, žádné licenční problémy, kompatibilita s kódem jiných jazyků, atd. Právě proto neuspěje ani D ani Rust. ---
Problém je akorát v tom, že při psaní C++ aplikace můžeš kdykoli plynule přejít do C a používat přímo céčkové knihovny. Což je vlastnost, kterou prakticky žádný jiný jazyk nemá (snad leda D).Což je velice silná vlastnost C++, a jiný jazyk by ji musel přebít něčím sakra silným.
Nemohl. Protože D i Rustu chybí v první řadě serióznost.Myslimže v Rustu už je na serióznost napsán pull request, prochází to review. Měli by to mergnout do další verze. Jestli si dobře pamatuju roadmapu, od verze 1.41 by měl být dodáván s kompilátorem i monokl a cylindr.
tj. napíšete v něm třeba operační systém, ovladače hw, můžete v něm psát kódy pro mikrokontrolery, atd. atd. atd.Ditto Rust. Ad. mikrokontrolery viz třeba tady, AFAIK můžeš taky už dnes napsat modul do Linuxu... Problém je když už tak nedostatek kompilátorů/toolchainů (příp. knihoven, abstrakcí) - což si všimni, že je nevýhoda, ve které jsem s tebou zcela souhlasil - nikoli na úrovni jazyka.
Aby mohl nějaký jazyk převálcovat C/C++ ... C++ je jediný jazyk, který má našlápnuto na to smést C z povrchu zemského. Žádný jiný dnešní programovací jazyk C nenahradí.Jak už jsem napsal, mně je nějaké převálcování C nebo C++ dost u zadku. Nevidim, proč by měl Rust něco převálcovat, stejně jako nevidim důvod, proč by C++ mělo převálcovat C (což se stejně nestane).
Což je velice silná vlastnost C++, a jiný jazyk by ji musel přebít něčím sakra silným.Naposledy, když jsem se rozhodl používat C knihovnu z C++, jsem si na to stejně napsal v C++ wrapper. Takže v podstatě stejný scénář, jaký by nastal v Rustu... Rust se v tomhle liší v podstatě jenom tím, že používání holého C API je o trochu větší opruz než v C++ (musíš používat unsafe atd.) a málo se to dělá, protože lidi nechtějí pokudmožno mít kód zamořený unsafe bloky/funkcemi (což je IMO dobře).
Nemohl. Protože D i Rustu chybí v první řadě serióznost.
a) C++ má vlastní standard, množství nezávislých kompilátorů.
S tímhle souhlasím. Oddělit specifikaci a implementaci je dobré a je to znakem vyspělosti, stability a serióznosti.
C++ má tu vlastnost, že C++ je stejně univerzální jako C, tj. napíšete v něm třeba operační systém, ovladače hw, můžete v něm psát kódy pro mikrokontrolery, atd. atd. atd.
Tohle může nabídnout jakýkoli jazyk z něhož po kompilaci vypadne strojový kód / assembler. Ty jazyky jsou vlastně jen prostředkem pro převod lidsky čitelného zápisu na kód, kterému rozumí počítač. A klidně to může být tak univerzální, že to půjde přeložit pro různé architektury včetně nějakých jednočipů.
Takže tady jde spíš o ten ekosystém kolem a o to, že nikdo nepřepíše všechny ty knihovny do nového jazyka, než o to, že by to v principu nešlo.
C++ je jediný jazyk, který má našlápnuto na to smést C z povrchu zemského. Žádný jiný dnešní programovací jazyk C nenahradí.
Vzhledem k tomu, že C++ je nadmnožina1 C, tak C++ nahradit C nemůže, protože C++ vždy v sobě to C bude obsahovat.
Což je velice silná vlastnost C++, a jiný jazyk by ji musel přebít něčím sakra silným.
Silná vlastnost to je, ale zároveň je to i slabina, protože C++ programy můžou obsahovat hodně nízkoúrovňového bordelu a nebezpečného kódu. A to jsou fakt věci, na které bych v aplikačním kódu nerad narážel. Tohle je vlastně klasický spor o to, zda je lepší mít víc možností i za cenu toho, že je programátor zneužije nebo bude dělat chyby. Řešilo se to tu celkem nedávno v souvislosti s vlákny. Někdo by programátorům tuhle možnost sebral, aby nedělali chyby, někdo by ji tam nechal… myslím, že tohle nemá jednoduché řešení.
[1] víceméně, ať mě tu zase někdo nechytá za slovo
Tohle může nabídnout jakýkoli jazyk z něhož po kompilaci vypadne strojový kód / assembler.Hnidopišská poznámka: To tak úplně neplatí. Třeba Go kompiluje do strojového kódu (žádný bytecode), ale ten kód má přibalený a je závislý na poměrně komplexním runtime obsahujícím GC, custom stack alokace atd. V tom asi driver psát nechceš
Nechci. Ale u céčka se tam taky přibalí nějaký kód/instrukce, které jsi nenapsal, ne? Takže to není nějaké černobílé buď a nebo, ale spíš plynulá škála toho, jak moc kódu navíc tam kompilátor různých jazyků přidává.
z výpisu ldd
:
linux-vdso.so.1 (0x00007fffbbb83000) libasan.so.5 => /usr/lib/x86_64-linux-gnu/libasan.so.5 (0x00007f86d5640000) libhidapi-hidraw.so.0 => /usr/lib/x86_64-linux-gnu/libhidapi-hidraw.so.0 (0x00007f86d5438000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f86d50a8000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f86d4e90000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f86d4a98000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f86d4890000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f86d4688000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f86d4468000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f86d40c8000) libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f86d3ea8000) /lib64/ld-linux-x86-64.so.2 (0x00007f86d6820000)
nic z toho jsem nenapsal a ni explicitně neuvedl jako závislost (jedinou – explicitní a chtěnou – závislost tam mám to USB HID API + ASAN). Ne, že by mě to nějak trápilo, ale nepřijde mi správné říkat, že program v C++ neobsahuje nic navíc, než co napsal jeho autor.
Stejně tak z GraalVM vypadne nativní binárka, která má přibaleno jen trochu kódu navíc.
nepřijde mi správné říkat, že program v C++ neobsahuje nic navíc, než co napsal jeho autor.A někomu něco podsouvat ti správné přijde?
Pak je ale část toho kódu, který je zde ve sdílených knihovnách, zakompilovaná do tvého programu, ne?
Pak je ale část toho kódu, který je zde ve sdílených knihovnách, zakompilovaná do tvého programu, ne?Záleží. Když nalinkuješ staticky standardní knihovnu, tak ano. Ale můžeš taky napsat program zcela bez jakýchkoli knihoven, včetně standardní. Takhle kompiluje programy třeba Go - vůbec nepoužívají libc a binárky, který z toho padaj, jsou zcela nedynamický. Řešej si sami syscally na každý platformě. Přijde mi to jako trochu prasárna, ale whatever. Ad. téma vlákna: V C je tohle velmi snadné, vzhledem např. k tomu, že alokace se dělá voláním funkce, nejsou výjimky (ignorujme stejmp) atd. V C++ to už je o trochu méně snadné a je to IMO zhruba stejné jako v Rustu: Je potřeba řešit nějak výjimky (resp. paniky v případě Rustu) a např. alokaci, tzn. v C++ buď přetížit de/alkoační operátory nebo je nepoužívat vůbec, podobně v Rustu (buď nahradit globální alokátor, nebo ho nepoužívat). V obou případech může (ale nemusí) být obvyklý komfort jazyka snížen, záleží, jak moc se ho bude člověk snažit zachovat.
Tohle může nabídnout jakýkoli jazyk z něhož po kompilaci vypadne strojový kód / assembler. Ty jazyky jsou vlastně jen prostředkem pro převod lidsky čitelného zápisu na kód, kterému rozumí počítač. A klidně to může být tak univerzální, že to půjde přeložit pro různé architektury včetně nějakých jednočipů.Bohužel nemůže. Jazyk si sebou nese i runtime knihovnu a další věci, které nutně potřebuje pro běh kódu. U naprosté většiny jazyků je právě toto neslučitelné s většinou low level použití typu operační systém nebo mikrokontroller. ---
Silná vlastnost to je, ale zároveň je to i slabina, protože C++ programy můžou obsahovat hodně nízkoúrovňového bordelu a nebezpečného kódu. A to jsou fakt věci, na které bych v aplikačním kódu nerad narážel.Pak ale nemá smysl mluvit o tom, že by Rust nahradil C. Protože C a jeho aplikace míří právě na ten nízkoúrovňový bordel. C/C++ vám dává výhodu naprosté kontroly toho co děláte, a jako vedlejší efekt to samozřejmě můžete také potentovat. Žádný jazyk, který neumožní totéž nemůže být konkurentem C/C++.
Bohužel nemůže. Jazyk si sebou nese i runtime knihovnu a další věci, které nutně potřebuje pro běh kódu.V Rustu je to zhruba podobné jako v C/C++, by default se linkuje standardní knihovna, runtime atd., ale můžeš psát kód i bez toho, použít vlastní alokátor atd.
Pak ale nemá smysl mluvit o tom, že by Rust nahradil C. Protože C a jeho aplikace míří právě na ten nízkoúrovňový bordel.Rust pro to má explicitní podporu, říká tomu
unsafe
kód. Proč jsi nenapsal rovnou na úvod, že o Rustu vlastně nic moc nevíš?
Ad ad 2) Na unsafe není nic inherentně špatného a ne™.
Přijde mi, že se projevujete trochu jako fachidiot, který se před 30 lety zvládl naučit jeden programovací jazyk, potažmo dostal do ruky kladivo, takže teď celý svět vypadá jako hřebík.
K vašemu pokusu o útok ad hominem bych dodal, že téma zní - čehož jste si patrně neráčil zatím všimnout: Proč Rust nenahradil C?Ne, to není téma, to byl výkřik nějakýho anonyma na začátku vlákna a ty ses toho chytil a stále na něj reaguješ i v odpovědích jiným lidem. Např. pro mě to vůbec žádné téma není.
Žádný jazyk, který neumožní totéž nemůže být konkurentem C/C++.
Univerzálnost C++ mě na jednu stranu fascinuje, ale na druhou stranu nevím, jestli je takhle široké rozpětí ideální. Na jednu stranu je skvělé, že stačí umět jeden jazyk a můžu v něm psát všechno od firmwaru do jednočipů, ovladačů a operačního systému až po účetní programy nebo hry, ale na druhou stranu to klade poměrně vysoké nároky na programátory a štábní kulturu. Což je asi důvod, proč jsou dost oblíbené i méně univerzální jazyky.
Tohle je vlastně klasický spor o to, zda je lepší mít víc možností i za cenu toho, že je programátor zneužije nebo bude dělat chyby.To s prominutím pletete dohromady dvě věci: 1) Bezpečnost výsledného kódu. 2) Dodržování štábní kultury. Udělat programovací jazyk stejně rychlý, schopný a efektivní jako C/C++ s tím, že navíc by byl mnohem bezpečnější - není problém. Takové jazyky existovaly a existují. Jen jsou ukecanější než C/C++, protože kompilátor potřebuje více informací, aby mohl více věcí kontrolovat. Mainstreamoví programátoři je nepoužívají, protože dávají přednost jazykům, kde lze něco napsat výrazem o 2 znaky kratším. Na druhé straně z ekonomických důvodů firmy chtějí ušetřit na programátorech, a tak zaměstnávají většinou různé nekňuby a nemehla - a ty nemají IQ ani zkušenosti na dodržování štábní kultury. Proto potřebují co nejblbější jazyk s co nejméně možnostmi, aby nemohli dělat co nemají. Takovým typickým jazykem pro neschopné je Java, která se snažila být ideálem pro tyto lidi.
Mainstreamoví programátoři je nepoužívají, protože dávají přednost jazykům, kde lze něco napsat výrazem o 2 znaky kratším.Dojmologie.
Na druhé straně z ekonomických důvodů firmy chtějí ušetřit na programátorech, a tak zaměstnávají většinou různé nekňuby a nemehla - a ty nemají IQ ani zkušenosti na dodržování štábní kultury. Proto potřebují co nejblbější jazyk s co nejméně možnostmi, aby nemohli dělat co nemají. Takovým typickým jazykem pro neschopné je Java, která se snažila být ideálem pro tyto lidi.Dojmologie.
Udělat programovací jazyk stejně rychlý, schopný a efektivní jako C/C++ s tím, že navíc by byl mnohem bezpečnější - není problém. Takové jazyky existovaly a existují. Jen jsou ukecanější než C/C++, protože kompilátor potřebuje více informací, aby mohl více věcí kontrolovat. Mainstreamoví programátoři je nepoužívají, protože dávají přednost jazykům, kde lze něco napsat výrazem o 2 znaky kratším.
Nemyslím si, že by lepší jazyk musel být nutně ukecanější. C++ má místy hnusnou/složitou syntaxi a ještě hnusnější standardní knihovnu. Kvůli zpětné kompatibilitě to nejde, ale kdyby to šlo: tak zahozením standardní knihovny a jejím čistým a promyšleným přepsáním by se z toho stal mnohem lepší jazyk.
Na druhé straně z ekonomických důvodů firmy chtějí ušetřit na programátorech, a tak zaměstnávají většinou různé nekňuby a nemehla - a ty nemají IQ ani zkušenosti na dodržování štábní kultury.
Nějak jsem si nevšiml, že by schopní programátoři nemohli sehnat práci, protože jsou drazí. Ti schopní jsou rozebraní a dobře placení. A co pak má dělat firma, která potřebuje programátory? Prostě musí brát ty průměrné a podprůměrné. Tohle je realita, současný stav – ne něco, co by si ty firmy vymyslely, aby ušetřily.
A Java je jazyk, který tuhle realitu dobře reflektuje a trefil správný poměr jednoduchosti a možností jazyka. Proto se ve firmách tolik používá. Na druhé straně jsou jazyky pro geniální samotáře, kteří budou onanovat nad vlastní genialitou a teoretickou dokonalostí svého jazyka. Ale pro týmovou spolupráci je takový člověk a jeho výtvor nepoužitelný a zatáhnout si něco takového do firmy je neštěstí, protože ta většina průměrných programátorů si s tím nebude vědět rady. C++ je někde mezi tím, je na jednu stranu hodně složité a záludné, ale na druhou stranu je to praktický jazyk s dlouhou historií, zralým ekosystémem a je v něm napsaná spousta softwaru, takže jen tak nezmizí (a tím pádem ani nevymřou C++ programátoři).
Nemyslím si, že by lepší jazyk musel být nutně ukecanější. C++ má místy hnusnou/složitou syntaxi a ještě hnusnější standardní knihovnu. Kvůli zpětné kompatibilitě to nejde, ale kdyby to šlo: tak zahozením standardní knihovny a jejím čistým a promyšleným přepsáním by se z toho stal mnohem lepší jazyk.Bezpečnější jazyk je obvykle ukecanější. Protože potřebuje mít nějaké informace ve zdrojovém kódu. C/C++ je prostě hnusné po syntaktické stránce i po stránce standardní knihovny. Hlavní důvod proč se prosadilo C je, že se svezlo s unixem. Hlavní důvod, proč se prosadilo C++ je, že to bylo C, které všichni známe. ---
A Java je jazyk, který tuhle realitu dobře reflektuje a trefil správný poměr jednoduchosti a možností jazyka. Proto se ve firmách tolik používá.S tím bych ostře nesouhlasil. Java se prosadila a používá proto, a jen proto, že firma Sun do prosazení Javy narvala astronomické miliardy dolarů. Sun financoval prosazení Javy tak mocně, až sám zkrachoval, a přestal existovat. Protože namísto kšeftu se Sun věnoval prosazení Javy. Když nalejete tolik peněz do prosazení i totálně blbého jazyka, jako nalil Sun do Javy, tak se ten jazyk prostě používat aspoň trochu bude. ---
Na druhé straně jsou jazyky pro geniální samotáře, kteří budou onanovat nad vlastní genialitou a teoretickou dokonalostí svého jazyka. Ale pro týmovou spolupráci je takový člověk a jeho výtvor nepoužitelný a zatáhnout si něco takového do firmy je neštěstí, protože ta většina průměrných programátorů si s tím nebude vědět rady.Já jsem tedy asi žil celý život v bludu. Celý život jsem měl zato, že nástroje pro práci mají sloužit tomu, co se dělá. Programovací jazyk není nic jiného než nástroj, asi tak jako kladivo, šroubovák, pila, apod. Dělat z programovací nástroje účel a cíl snažení je zaměňovat prostředky a cíl snažení. Každý programovací jazyk dneška je v zásadě jednoduchoučký jako pro mentální retardy. Neznám žádný programovací jazyk, kde by člověk potřeboval doktorát. Nevím proto moc o čem mluvíte. Já naopak trpím tím, že většina moderních programovacích jazyků si zbožští jako zlaté tele pokládané na oltář bohu nějakou teoretickou věc, a tím vznikne nepraktický programovací jazyk. Byl bych první, kdo by jásal, kdyby někdo tvořil praktický programovací jazyk - jako nástroj. Java si zbožštila OOP. Rust si zbožštil bezpečnost pointerů. C++ si zbožštilo šablony, generické programování. ---
C++ je někde mezi tím, je na jednu stranu hodně složité a záludné, ale na druhou stranu je to praktický jazyk s dlouhou historií, zralým ekosystémem a je v něm napsaná spousta softwaru, takže jen tak nezmizí (a tím pádem ani nevymřou C++ programátoři).C++ právě záludné není. C++ se chová dosti logicky. Jeho složitost je jenom zdánlivá, C++ je postaveno na několika málo principech, které se všude opakují.
Bezpečnější jazyk je obvykle ukecanější. Protože potřebuje mít nějaké informace ve zdrojovém kódu.Jaké informace máš na mysli? Rust moc informací navícv tomhle ohledu typicky neobsahuje. Občas nějaké ty lifetimes, to ano, ale toho obvykle moc není. Celkově mi přijde spíš méně ukecaný než C++, ačkoli záleží jak v čem.
C++ právě záludné není.C++ zcela určitě záludné je, mj. v tom, že obsahuje velké množství implicitního chování. Různé typy se implicitně konvertují jeden na druhý, volání funkce může implicitně končit všude možně (overload resolution je směšně složitý), vytvoření reference je implicitní, u kontejnerů stdlib se provádí implicitně hluboké kopie, atd. Celé je to prošpikováno nepěkným množstvím složitého implicitního chování. Zajímavé je, že i přes spoustu toho implicitního chování je C++ stále dost ukecaný jazyk.
C++ zcela určitě záludné je, mj. v tom, že obsahuje velké množství implicitního chování. Různé typy se implicitně konvertují jeden na druhý, volání funkce může implicitně končit všude možně, vytvoření reference je implicitní, u kontejnerů stdlib se provádí implicitně hluboké kopie, atd. Celé je to prošpikováno nepěkným množstvím složitého implicitního chování. Zajímavé je, že i přes spoustu toho implicitního chování je C++ stále dost ukecaný jazyk.Já jsem čekal, že vyjmenujete úplně jiné záludnosti C++. A ne tento čajíček.
---
Takže si v C++ napíšeš vlastní kontejnery, proč ne. A teď si vem, že bys třeba místo C++ použil Rust. Sáhneš do kontejneru mimo a stane se co? V Rustu dostaneš panic ze standardního kontajneru a za minutu je opraveno. Jako bonus jsi ušetřil měsíc psaní vlastních kontejnerů, ve kterých stejně nasekáš mraky chyb a budou mnohem hůř odladěné, než ty ve standardní knihovně.
Musíš řešit mimo jiné move sémantiku, in-place konstrukci, vlastní alokátory a podobné chuťovky.Tipuju, že tohle on vůbec neřeší... Jinak v tomhle je zajímavé, jak má Rust úplně opačný default: Datové struktury by-default nejsou kopírovací, naopak by default jsou přesouvací (movable). Takže člověk pro typy ani nemusí implementovat move semantics - funguje to out of the box. A to mnohem lépe než v C++, protože se neporušuje RAII. V C++ jsou move semantics dost zprasené, je to spíš glorifikovaný swap. Jsem z toho popravdě dost zklamaný. Taky mi přijde mnohem lepší, když je kopírování explicitní, ne implicitní jako v C++, kde když si člověk nedá pozor, zkopíruje se mu věcí, že se nestačí divit. Na druhou stranu Rust má nevýhodu, že move je někdy potřeba explicitně zakázat (pin API, mam z něj zatím trochu smíšené pocity) a taky nepodporuje emplacing (byla pro to jednu dobu experimentální podpora v nightly, ale odstranili to, protože to nefungovalo dobře, a čeká se teď na nový, lepší návrh). Tož tak.
Můj názor je napsat si své vlastní kontejnery a nad STL zmlámat hůl.
Jenže jak potom kombinovat kód od různých autorů? Co když budu psát knihovnu pro ostatní nebo naopak používat cizí knihovnu a ty metody budou mít na vstupu nebo výstupu více hodnot (tzn. nějakou kolekci, pole, seznam…)? Pro srovnání: v Javě by ta metoda přijímala nebo vracela Collection
, což je jednoduché rozhraní definované ve standardní knihovně, které může kdokoli implementovat (a pravděpodobně si i vystačí s implementacemi ze standardní knihovny).
Překládat si všechno sám je v C++ základ. Jednoduše proto, že výsledné knihovny jsou dosti závislé na parametrech kompilátoru. Nepoužívám žádné globální/sdílené knihovny u C++.
Tak to už rovnou můžu psát v tom Rustu nebo třeba v Déčku. Nebo napsat v C/C++ jen to nejnutnější a zbytek v Javě, kde si ty vlastnoručně zkompilované nativní knihovny přibalím do JARů k aplikaci.
Výhoda C/C++ pro mě je v tom, že se dobře integruje se systémem a s nainstalovanými knihovnami, na které se může dynamicky napojit a které lze aktualizovat nezávisle na aplikaci (při dodržení zpětné kompatibility, např. u bezpečnostních oprav knihoven).
Tady nevidim žádnou pointu. V Rustu můžeš udělat to samé, co v C++ - exponovat C-kompatibilní API/ABI.Ta pointa je v tom, že každá platforma definuje C ABI, nikoli Rust ABI.
1) Protože Rust není tak dobrý, a nemá dostatečně dobré vlastnosti, aby dokázal nahradit C/C++.Rust neni vselek, ale v rade scenaru muze byt lepsi volba. Go taky neni top jazyk co do vlastnosti, ale presto rada programatoru po nem sahne, protoze resi nektere veci mnohem elegantneji nez C/C++.
2) Protože Rust není seriózní programovací jazyk na rozdíl od C/C++ (nemá nezávislý standard, nectí zpětnou kompatibilitu, ...).To asi malokoho trapi. I C++ dlouho dobu nemelo standard a rozsirilo se. A i kdyz standard melo, tak prekladace byly proslule tim, ze nepodporovaly vsechno a poradne, takze kolem prelomu tisicileti bylo zvykem, ze soucasti guidelines projektu bylo i to, ktere vlastnosti jazyka se muzou pouzivat, aby to slo prelozit na ruznych prekladacich a platformach.
3) Rust nemá definováno přesné chování v řadě situacVytahovat nedefinovane chovani pri srovnavani s jazykem C je dost chucpe.
4) Protože C je mnohem přenositelnější a univerzálnější jazyk než Rust.Otazka vkusu. Slusi se dodat, ze ta univerzalita je vykoupena tim, ze programatorovi je umozneno udelat vyrazne vic chyb.
5) Protože C má konzistentní a stabilní ABI, což umožňuje velice mnoho věcí.IIRC, to nikde ve standardu neni napsane a s rozsirenim jazyka to moc nesouvisi. ABI C++ budiz prikladem.
6) Protože Rust přišel o pár desetiletí později než C/C++.To je tak jedine, s cim se da souhlasit.
Jenomže C/C++ má své typické pole použití: Univerzální jazyk, kde ...Pouziti slov "univerzalni jazyk", pricemz nasleduje omezujici vycet, je takove mile. Vylozene manipulativni je pak davat jazyky C a C++ dohromady a vlastnosti jednoho spojovat s obema. C opravdu nevynika rychlosti vyvoje, v C++ zase clovek ztraci tu zminovanou totalni kontrolu...
Ad 2) Tak si to myslete dál, že nikoho netrápí, že má před sebou indiferentní nedefinovaný jazyk, od kterého nemůže přesně vědět, co může čekat dnes či za rok - ale pak pěkně prosím nedávejte prosím takové blbé otázky jako "proč Rust nenahradil C". Všechny jazyky, které nebyly jen štěkem, a jsou dlouhodobou stálicí, mají - jasný standard a zpětnou kompatibilitu.Treba takovy Python nebo PHP...
Ad 4) Já znám jazyky, které umožňují stejnou univerzalitu jako C, a přitom jsou daleko bezpečnější než Rust. Třeba i ta stará herka Ada to zvládla velice dobře. Rust to nezvládl.Tak sem s nima. Otazka je, jestli opravdu ta bezbreha univerzalita je to, co programatori realne chteji/potrebuji. Ada sice nektere veci resi lip, ale programovat v ni je tezce PITA, vedle toho Rust si programatori voli dobrovolne, protoze prekvapive se jim v tom dobre programuje a resi to nektere situace, ktere generuji caste chyby. Za me duraz implicitni duraz na immutabilitu je krok velmi dobrym smerem.
Ad 5) A proto snad každý programovací jazyk má nějakou formu, jak zavolat funkci v C ABI.Jak uz jsem psal v predchozim prispevku, C++ ma priserne ABI a jeho rozsireni to neni nijak nebrani, nevim, proc by to melo branit Rustu. Volani funkci z C je ciste otazkou rozhrani a u rady jazyku se to resi nejakou formou FFI, coz s jazykem nemusi souviset vubec. Fakt, ze vetsina jazyku ma out-of-the-box rozhrani pro C neni dano nejakou jeho uzasnosti toho rozhrani, ale proste tim, ze temer kazdy programovaci jazyk potrebuje pristup k rozhranim OS, resp. k standardnim knihovnam, ktere jsou v drtive vetsine psany v C, takze je to jen takova znouzectnost.
Vylozene manipulativni je pak davat jazyky C a C++ dohromady a vlastnosti jednoho spojovat s obema. C opravdu nevynika rychlosti vyvoje, v C++ zase clovek ztraci tu zminovanou totalni kontrolu...Já už si podobné řeči u vás překládám jako "deda.jablko neumí C++". ---
Tak sem s nima. Otazka je, jestli opravdu ta bezbreha univerzalita je to, co programatori realne chteji/potrebuji. Ada sice nektere veci resi lip, ale programovat v ni je tezce PITA, vedle toho Rust si programatori voli dobrovolne, protoze prekvapive se jim v tom dobre programuje a resi to nektere situace, ktere generuji caste chyby. Za me duraz implicitni duraz na immutabilitu je krok velmi dobrym smerem.Je to zvláštní, ale já neznám osobně nikoho kdo by chtěl programovat v Rustu. Ani já po tom netoužím. Zato znám lidi, kterým se líbí Ada. A znám stovky programátorů v C++. Takový poměr bude asi reálný po celém světě. ---
Jak uz jsem psal v predchozim prispevku, C++ ma priserne ABI a jeho rozsireni to neni nijak nebrani, nevim, proc by to melo branit Rustu. Volani funkci z C je ciste otazkou rozhrani a u rady jazyku se to resi nejakou formou FFI, coz s jazykem nemusi souviset vubec.C++ má nejlepší "ABI" pro C. C++ je slučitelné na úrovni zdrojových kódů i většinově na úrovni ABI. To, že C++ mangluje názvy identifikátorů do linkeru je ten poslední problém. ---
Fakt, ze vetsina jazyku ma out-of-the-box rozhrani pro C neni dano nejakou jeho uzasnosti toho rozhrani, ale proste tim, ze temer kazdy programovaci jazyk potrebuje pristup k rozhranim OS, resp. k standardnim knihovnam, ktere jsou v drtive vetsine psany v C, takze je to jen takova znouzectnost.C je stalo esperantem v sw světě. Vám se to nelíbí, tak z toho děláte z nouze ctnost, ale to je jen váš subjektivní názor.
Já už si podobné řeči u vás překládám jako "deda.jablko neumí C++".Tve argumenty presvedcivosti jen pretekaji.
Je to zvláštní, ale já neznám osobně nikoho kdo by chtěl programovat v Rustu. Ani já po tom netoužím. Zato znám lidi, kterým se líbí Ada. A znám stovky programátorů v C++.Tak se bez nekdy podivat mezi lidi, zejmena ty mladsi. V me socialni bubline z desitek C++ programatoru (15-20 let zpet) zustal asi jediny, pan v duchodu. Vsichni ostatni migrovali jinam, Vetsinou C#, Java nebo Python, coz je jazyk, ktery nikdo nebude pouzivat, protoze nema standard ani nedodrzuje zpetnou kompatibilitu. Co se tyce Ady, rekl bych, ze to budou opet panove duchodveho veku, z dnesni generace programatoru ji prakticky nikdo nezna. Ale kdyz jsme v minulosti pouzivali jazyk, ktery mel typovy system inspirovany Adou, vsichni z toho byly nestastni, az v depresi, z toho, jak je to neprijemne.
C je stalo esperantem v sw světě. Vám se to nelíbí,Co mi to podsouvas? Ja proti pouzivani C nic nemam, ale jsem natolik soudny, ze dokazi vnimat i jeho negativni stranky a neberu to jako neco, co seslal buh na chramovou horu na kamennych dernych stitcich, a proto se to musi pouzivat vsude a na vsechno.
5) Protože C má konzistentní a stabilní ABI, což umožňuje velice mnoho věcí.Ale pro C je to pravda, vsichni to dodrzuji, narozdil od toho C++, kde to prinasi spoustu problemu a mnohdy knihovny uvnitr napsane v C++ (protoze je v tom jednodussi spoustu veci naprogramovat) maji interface v C prave z tohoto duvodu. C knihovnu nahrajes v podstate v jakemkoliv jazyku, dokonce i dynamicky (dlsym, GetProcAddress), coz taky vsechny vyssi jazyky delaji, kdyz potrebuji C knihovnu.
2) Puntičkářské dodržování zpětné kompatibility.Blah. C++ taky občas udělá nekompatibilní změny (C++11, C++14, C++17). Co se týče "puntíčkářského" dodržování zpětné kompatibility v C, zkus si následující kód zkompilovat s C90 a C99:
int main() {
const int i = 2 //**/ 2
;
return i;
}
To je něco, co se mi s nějakým Go, Rustem, apod. nemůže nikdy stát. Kód v Rustu, který napíši dnes, s největší pravděpobností pohoří za rok, dva nebo tři - při těch změnách jazyka.Vytáhl jsem si projekt z konce 2016 a aktuální Rust to normálně přeloží včetně všech dependencí. Rust má kvůli zpětné kompatibilitě mj. edice (víceméně něco jako různé verze standardů v C/C++). Souhlasim, že jsou méně kozervativní než C/C++ a šance na problém je asi o něco větší, nicméně zpětnou kompatibilitu berou také docela vážně. Veškeré nové featury v edici 2018 nijak neovlivnily schopnost kopmilátoru kompilovat kód z 2015. Go je na tom se zpětnou kompatibilitou pravděpodobně lépe než Rust co se týče jazyka jako takového, bude na tom ale hůř v oblasti dependencí, protože semver specifikace dependencí podporuje teprve nedávno. Rust je má od začátku. C/C++ ti v oblasti dependencí ukáže velký vztyčený prostředníček.
C/C++ ti v oblasti dependencí ukáže velký vztyčený prostředníček.
To přece není až tak věc C/C++ jako spíš distribucí, jednotlivých knihoven a sestavovacích nástrojů. U C/C++ je snaha používat sdílené knihovny – což je ta těžší cesta, ale podle mého správnější. Oproti tomu jiné jazyky resp. jejich ekosystémy na tohle kašlou a zjednodušují si to tím, že všechny závislosti přibalí k programu.
To přece není až tak věc C/C++ jako spíš distribucí, jednotlivých knihoven a sestavovacích nástrojů.Tam je to špatně celé ze shora až dolů. Jistá naděje jsou moduly v C++20, ale nevim no, uvidíme...
U C/C++ je snaha používat sdílené knihovny – což je ta těžší cesta, ale podle mého správnější.Já ti nevim. Taky jsem býval fanoušek sdílených knihoven v distribučních balíčcích, poslední dobou už moc ne. Funguje to dobře pro takové ty hodně rozšířené fundamentální věci jako různé kodeky základních široce používaných formátů (komprese, obrázky, apod.), systémové GUI toolkity a takovéhle věci. Pro ostatní věci až tak ne, mi přijde. Nedávno jsem si instaloval maličký prográmek v Hakellu a balíčkovací systém mi kvůli tomu natahal několik desítek balíčků haskellovských závislostí. Být to sestaveno více staticky, nejspíš by to mělo zlomek tý velikosti a bylo v jednom nebo několika málo balíčcích. Když se mi pak s každou aktualizací systému stahovala půlka haskell ekosystému, tak jsem to celé odstranil. Nehledě k tomu, že proces mapování dependencí na balíčky nějaké konkrétní distribuce je nespolehlivý, nepredikovatelný opruz.
Nedávno jsem si instaloval maličký prográmek v Hakellu a balíčkovací systém mi kvůli tomu natahal několik desítek balíčků haskellovských závislostí.
Chápu, třeba v JavaScriptu to bude ještě horší.
Být to sestaveno více staticky, nejspíš by to mělo zlomek tý velikosti a bylo v jednom nebo několika málo balíčcích.
Jenže to je dané chybným návrhem těch knihoven, nevhodnou granularitou, a tím, že autor té aplikace nad závislostmi nepřemýšlí a natahá si tam náhodné knihovny a jejich tranzitivní závislosti a je mu to jedno. Je to prostě špatně odvedená práce a vadná kultura.
Máš pravdu v tom, že když se to kompiluje staticky, může kompilátor vyházet nevyužitý kód a zahrnout jen nějakou podmnožinu. Na druhou stranu tam máš duplicitní kód napříč programy, který je neudržovaný/neudržovatelný.
Nehledě k tomu, že proces mapování dependencí na balíčky nějaké konkrétní distribuce je nespolehlivý, nepredikovatelný opruz.
Mně se celkem líbí, jak má balíčky udělané Guix, kde můžeš mít instalováno více verzí od jednoho programu/knihovny a ten systém je na to připravený, není to tam jen tak dodatečně dohackované. A pak se mi líbí systém knihoven v Javě (Maven), kde jsou zase dobře vyřešené jedinečné názvy (groupId/artifactId/version)… tohle většina jiných systémů nezvládla a mají v tom bordel.
Jenže to je dané chybným návrhem těch knihoven, nevhodnou granularitou, a tím, že autor té aplikace nad závislostmi nepřemýšlí a natahá si tam náhodné knihovny a jejich tranzitivní závislosti a je mu to jedno. Je to prostě špatně odvedená práce a vadná kultura.Mně ani tak nevadil počet těch dependencí jako spíš hlavně to, že se řešily přes balíky distribuce. IMO v takovémhle případě to nemá žádnou výhodu.
A pak se mi líbí systém knihoven v Javě (Maven), kde jsou zase dobře vyřešené jedinečné názvy (groupId/artifactId/version)… tohle většina jiných systémů nezvládla a mají v tom bordel.No takže javovské dependence taky neřešíš přes distribuci, ne?
Mně ani tak nevadil počet těch dependencí jako spíš hlavně to, že se řešily přes balíky distribuce. IMO v takovémhle případě to nemá žádnou výhodu.
A jak by se to mělo řešit? Proč bych měl mít v OS spousty různých balíčkovacích systémů – pro každý jazyk jiný nebo dokonce několik pro jeden jazyk a ještě k tomu duplikovat stažené balíčky mezi uživateli?
Vždyť je to pořád dokola to samé:
Proč bych měl mít v OS spousty různých balíčkovacích systémů – pro každý jazyk jiný nebo dokonce několik pro jeden jazyk a ještě k tomu duplikovat stažené balíčky mezi uživateli?Huh? Kdyby byl ten Haskell prográmek sestaven staticky (více staticky), tak si stáhnu jeden distribuční balíček nebo třeba jeden nebo několik málo balíčků nějakého základního Haskell runtime a k tomu ten prográmek.
Vždyť je to pořád dokola to saméNení. Ty balíčkovače mají jiné kompetence a řeší trochu jiné věci. Balíčkovacím systémem distra si řídíš, co máš v systému. Balíčkovací systém jazyka spravuje dependence nějakého software na různých systémech. Určitý přesah tam je, ale není to to samé.
Huh? Kdyby byl ten Haskell prográmek sestaven staticky (více staticky), tak si stáhnu jeden distribuční balíček nebo třeba jeden nebo několik málo balíčků nějakého základního Haskell runtime a k tomu ten prográmek.Resp. takhle: On ten balíček možná staticky sestaven byl (už nevim), ale nepřijde mi smysluplné, že jsem k tomu musel použít balíčkovač distribuce.
No takže javovské dependence taky neřešíš přes distribuci, ne?
Ne, ale je to špatně. Chtělo by to mít jednak možnost systémové instalace javovských knihoven a jednak to propojit s Mavenem, aby si knihovny bral odněkud z /usr/share/…
, pokud tam jsou a ne jen z ~/.m2/repository
Ale, ač bych se nerad mýlil, tak od prohlášení že je to stabilní, tak si žádné BC nevybavuji.Ale jo, breaking changes byly i po 1.0, ale to se děje snad v každém jazyce včetně C a C++. Jde spíš o to, že lidi vidí nové featury v jazyce a mají dojem, že tím pádem se jazyk mění. Nedochází jim, že ty změny jsou zpětně kompatibilní (stejně jako třeba u C++), že existují edice atd. Takže ty breaking changes IMO +- nejsou o horší než v C, C++. Mimochodem, triviální způsob jak v Rustu potenciálně porušit kompatibilitu je přidat metodu u primitivního typu nebo typu ze standardní knihovny. Protože si můžeš k libovolnému typu (včetně primitivních) přidat vlastní metody pomocí vlastní traity, přidání stejně pojmenované metody v jazyce/stdlib ti pak může rozbít kód. Samozřejmě když si přidáváš metody k primitivním typům nebo typům ve standardní knihovně měl bys s tímhle počítat (!) a člověk si moc nemá na co stěžovat, když se tohle stane, ale technicky vzato se stále jedná o breaking change.
V C++ to sice taky neni zadny med, ale celou knihovnu (C++ uvnitr, C rozhrani) kompilujes jednim kompilerem, coz prinasi spoustu vyhod.To samé platí o Rustu. V podstatě se to v Rustu dělá úplně stejně jako v C++. Dokonce to v některých ohledech jde i líp - když si strukturu označíš jako
repr(C)
, tak ti Rust kopmilátor zajistí, že bude mít céčkovou reprezentaci. V C++ si naprosti tomu musíš dát pozor, aby struktura zůstala vždy POD. (Možná by na to fungoval nějakej static_assert
).
Přijde mi, že si pleteš Rust s Gočkem nebo Javou nebo něčim takovým...
Já se obávám, že stejně jako Miloslav Ponkrác, nehrajete fér. Samozřejmě že Rust měl svá dětská léta kdy se syntaxe divoce měnila. Ale, ač bych se nerad mýlil, tak od prohlášení že je to stabilní, tak si žádné BC nevybavuji.My hrajeme fér. Odpovídáme ve vlákně "Jak je možné, že Rust ještě nevytlačil C?". Jinak řečeno, mezi řádky otázky je tvrzení, že Rust je stejně vyspělý, solidní, seriózní, a ustálený, a na mnoha platformách rozšířený jako C. Pravda je ovšem taková, že Rust má k tomuto ještě velice daleko. --- Bjarne Stroustrup začal pracovat na C++ 1979. Sám napsal několik verzí kompilátorů do C. V roce 1985 vydal knížku o C++ jazyce a její popis. Do této chvíle one man show. Už v roce 1988, tedy za pouhých 9 let po prvním škrábnutí Stroustrupa na C++, nezávislá firma udělala kompilátor. O rok později první ISO standard. V roce 1991 jsem já osobně zakoupil Borland Turbo C++, další nezávislý kompilátor C++. --- Popsal jsem dění v rozsahu 13 let od startu C++. Graydon Hoare začal pracovat na Rustu 2006. Něco pořádného se začalo dít až když Mozilla do toho začala lít prachy a mnoho lidí začalo pracovat na Rustu. První kompilátor 2010. -- Dnes je to tedy 13 let. Srovnání historie C++ a Rustu nevypovídá pro Rust dobře. Není k dispozici standard. Žádná nezávislá firma nevydává kompilátory pro Rust. Rust je několik let nejoblíbenějším jazykem Stack overflow. C++ nic takového jako award nesbíral, ale jeho rozšíření, dozvuk - byl u C++ slyšet sakra v každém koutě softwarového světa. 13 let po vzniku C++ každý věděl, co to C++ je. C++ rozšiřovaly firmy. Rozšiřoval ho Borland, rozšiřoval ho Microsoft. Na chvíli zmizel z reflektorů, ale jakmile se rozšířily mobily a embedded, C++ znovu má raketový nástup. Protože prostě C++ nabízí velké výhody a potřebné vlastnosti pro tyto sféry. A Rust? Kdo ho propaguje? Mozilla... Kdo ho skutečně nezbytně potřebuje? --- Chtěl jsem jenom říci, že pokud se sebou Rust něco neudělá, tak bude za pár let zápasit o svou existenci. Chtít po Rustu metu všeobecné náhrady C/C++ je pak čirá ztráta smyslu pro realitu.
S tím, že by jazyk měl mít standard/specifikaci a pak nezávislé implementace, souhlasím.
Ale o čem má jinak vypovídat to srovnání? O schopnosti autorů? O kvalitách jazyka? Vždyť to byla úplně jiná doba – oba ty úseky jsou sice dlouhé 13 let, ale to je tak všechno, co mají společného, jinak jsou ty podmínky úplně jiné. Dřív bylo běžné psát v assembleru a „čistém“ céčku, což je poměrně zoufalství a pak tam byly další jazyky, které ale byly na tehdejším hardwaru pomalé. Takže když do toho přišlo C++, i když bylo dost špatné, tak uspělo. Dneska máme o několik řádů výkonnější hardware a spoustu vyšších jazyků, které na něm běží dostatečně rychle, i když se třeba jen interpretují, nebo překládají za chodu JITem nebo mají GC atd. Máme tu Javu, Python nebo pak různé Lispy, které už jsou dneska taky rychlé… možností je spousta a každý si vybere ten svůj šálek čaje (kafe). Assembler nebo „čisté“ céčko je sice pořád zoufalství, ale nikdo tě v nich už nenutí psát (můžeš to udělat třeba v té Javě, která je řádově pohodlnější a bezpečnější a tu C knihovnu odtamtud jen zavolat nebo v C napsat jen nějakou kritickou část nebo integraci s OS). Uspět za téhle situace s novým lepším jazykem je výrazně těžší než tehdy.
různé Lispy, které už jsou dneska taky rychlé…Lispy jsou "taky rychlé" už imho déle než ta java a python.
13 let po vzniku C++ každý věděl, co to C++ je.Ale ty zjevně víš, co Rust je
A Rust? Kdo ho propaguje? Mozilla... Kdo ho skutečně nezbytně potřebuje?Za mě: První Rust kód za peníze jsem napsal v roce 2016, tzn. 10 let po první čárce a 6 let po prvním kompilátoru. To mi nepřijde zlý. Letos jsem zatím zaznamenal 3 nabídky práce v oblasti programování v Rustu, ani jedno z toho nebyla Mozilla a ani jsem je nijak aktivně nevyhledával, objevily se víceméně spontánně. Aktuálně psaní v Rustu tvoří zhruba polovinu mého příjmu. Používají ho také velké firmy jako Google, Facebook apod. Samozřejmě že Rust může selhat a upadnout do obskurity, to je asi jasné. To se může stát každému jazyku a novým jazykům obvzlášť. Ale aktuálně není IMO moc důvod k takovým obavám.
Muze mi nekdo vysvetlit, proc Rust jeste nevytlacil C?Tohle bude nejspíš trolling, ale minimálně bych se před takovou otázkou zamyslel, proč C++ nevytlačilo C...
Jako kdyby soudruzi z tzv. Demokratické strany scházející se v kavárně Karla Marxe byli nějaká výhra…
Mimochodem, když už se tu tolik řeší C++, v poradně mám jeden dotaz.
struct VlastnikZdroje { unsigned PocetReferenci; TypHandle Handle; void createRef() {++PocetReferenci;} void deleteRef() {if (--PocetReferenci == 0) close();} void close(); void open(TypHandle NovyHandle) {close(); Handle = NovyHandle; PocetReferenci = 0;} }; class TridaKPouzivani { ... private: VlastnikZdroje * UkazatelNaZdroj; };
Odpověděl jsem pod tím dotazem, kde je to víc k tématu.
1) Já bych začal tím, že bych rozhodně nikdy nepoužíval typ uint16_t. A to jednoduše proto, že takový typ na mnoha platformách vůbec nemusí existovat. Pokud platforma/procesor nedokáže poskytnout 16bitový integer, tak prostě v C/C++ vůbec uint16_t neexistuje.Je kouzelne, jak Ponkrac v prispevcich nekde nahore horuje za to, ze jazyk, aby byl bran jako seriozni, musi mit precizne definovane chovani. A jako priklad dava C/C++, kde nejsou presne definovany ani zakladni skalarni typy, resp. jejich rozsahy a jejich chovani. Dale, datovy typ ma vyjadrovat zpusob reprezentace hodnoty (jeji ulozeni) a mnozinu pripustnych hodnot. Proto se datovy typ voli podle toho, jake hodnoty ma reprezentovat, ne podle toho, jestli na dane platforme existuje, nebo ne. Takze uint16_t je naprosto validni volba, kdyz to clovek chce/potrebuje.
Zrovna 16bitový integer na mnoha 32bitových platformách vůbec neexistuje.A nicemu to nevadi, protoze prekladac (a od toho tam je) se s tim umi vyporadat.
Je kouzelne, jak Ponkrac v prispevcich nekde nahore horuje za to, ze jazyk, aby byl bran jako seriozni, musi mit precizne definovane chovani. ... Takze uint16_t je naprosto validni volba, kdyz to clovek chce/potrebuje.Kdybyste napsal, že neznáte ani základy C/C++, udělal byste mnohem lépe. To je to hlavní, co jste sdělil. Datový typ uint16_t je podle C++ standardu "optional", tedy nemusí existovat. Existuje tehdy, a pouze tehdy, pokud procesor má přímý 16bitový typ. Když potřebujete datový typ 16 bitů dlouhý, tak validní volba podle C++ standardu je uint_least16_t, ten existuje vždy. Ovšem namísto toho můžete použít unsigned short, protože ten je zaručeně také minimálně 16 bitů dlouhý. ---
A nicemu to nevadi, protoze prekladac (a od toho tam je) se s tim umi vyporadat.Pište prosím jen, když budete o daném tématu něco znát. Viz výše.
Jak se pak řeší situace, kdy chci kus dat (načtený třeba z disku nebo ze sítě) namapovat na strukturu nebo konkrétní datový typ? Dejme tomu, že vím, na které pozici v těch datech bude 16bitové číslo, že to má správnou endianitu, že je to zarovnané… Tak tam bych to konkrétní místo v paměti mohl přetypovat na uint16_t
(nebo třeba strukturu obsahující několik takových prvků)… ale když se na existenci uint16_t
spoléhat nemůžu a musím použít uint_least16_t
. tak hrozí, že by mi to načetlo víc než ty dva bajty a dostal bych úplně jinou hodnotu nebo bych překročil nějakou hranici.
uint16_t
. Mohl bys dát příklad takové platformy?
Pokud procesor neumí pracovat s 16bitovými čísly, pak to stejně ve struktuře nepoužijete. Procesor s tím pak přímo pracovat nemůže, a vám nazbývá nic jiného než to přečíst jako 2 bajty (třeba pomocí char pointeru).To nepomůže - standard C negarantuje, že
char
má 8 bitů. char
může mít klidně 64 bitů. Zjisti si něco o makru CHAR_BIT
. Programovat program s předpokladem, že char
má 8 bitů, a že tudíž pole 2 charů
má 16 bitů, je velice naivní a neseriózní.
Už několikátý příspěvek operuješ s platformami bez uint16_t
. Mohl bys dát příklad takové platformy?
Bývá a bývávala to často doména RISC procesorů.
---
To nepomůže - standard C negarantuje, že char
má 8 bitů.
To vskutku negarantuje. Ovšem pro 99,99 % platform je char 8 bitů. Také garantuje, že je to nejmenší adresovatelná jednotka paměti (s výjimkou bitových polí). A standard C++ rovnou uvádí, že char má velikost 1 byte.
---
To může. Za předpokladu, že těch 64 bitů je nejmenší softwarově adresovatelná jednotka paměti. Až se s takovou platformou setkáte, dejte mi vědět. ---char
může mít klidně 64 bitů. Zjisti si něco o makruCHAR_BIT
.
Programovat program s předpokladem, žeJá myslím, že je to velice seriózní. Protože standardní I/O knihovna C/C++ pracuje s polem charů. Jinak řečeno, když do I/O knihoven pošlete dva chary, tak na úložišti se objeví dva bajty. Za každého počasí.char
má 8 bitů, a že tudíž pole 2charů
má 16 bitů, je velice naivní a neseriózní.
Bývá a bývávala to často doména RISC procesorů.Buď prosím konkrétní. Ie. která implementace C/C++ neposkytuje
uint16_t
a pro jakou platformu.
A standard C++ rovnou uvádí, že char má velikost 1 byte."Byte", tak jak je definován v C++, se od charu velikostí neliší, může klidně taky mít 64 bitů. Pointa je v tom, že je dost šílené psát kód, který skutečně pedanticky počítá se všemi možnostmi, které standard dovoluje - to bys fakt musel být připraven na to, že char má 64 bitů, znaménkové typy jsou doplněk do 1 a podobné obskurity. Takže realisticky člověk píše C/C++ kód, který je nějakým způsobem omezen co do podpory platforem. Takže když někomu vyčteš, že používá
uint16_t
, tak nestačí to zdůvodnit standardem a tím, že kompilátor nemusí uint16_t
podporovat, ale měl bys vysvětlit, proč právě ta tvoje úroveň omezení / asumpcí o platformě je ta správná, které platformy nemají uint16_t
a proč by je měl autor kódu podporovat. Je totiž dost možné, že software, který ten člověk píše, vůbec pro takovou platformu není relevantní.
Pokud umí procesor pracovat s 16bitovými čísly - pak máte i uint16_t typ.Tak mame tu hezkou definici kruhem. Ale vidim, ze tomu rozumis jako obvykle.
Pokud procesor neumí pracovat s 16bitovými čísly, pak to stejně ve struktuře nepoužijeteJe nutne rozlisovat mezi (1) provadet aritmeticke operace s 16bitovymi cisly (scitani, nasobeni, ...) a (2) manipulovat s 16bitovymi cisly, ve smyslu byt schopen je nacitat a ukladat. Rada procesoru, typicky RISC, neumi (1), ale umi (2), coz absolutne nebrani existenci typu uint16_t na techto platformach. Typovy system C je na to staveny. Pokud by na danem procesoru existovala instrukce pro cteni jednoho bytu a zaroven byl schopen procesor pracovat s vetsimi hodnotami, nebrani prekladaci nic v tom, aby operace s hodnotami typu uint16_t prelozil na vic dilcich instrukci. Neni to zadna veda, prekladace to delaji bezne, treba u 32bitovych procesoru a 64bitovych hodnot. Ten problem, kdy nemuze existovat uint16_t a zaroven existuje uint_least16_t je v pripade, ze procesor dokaze adresovat jen 32bitova a vetsi slova. Nic takoveho jsem v zivote nepotkal, i kdyz si dokazu teoreticky predstavit nejaky DSP, ktery tim trpi.
C/C++ nezaručuje existenci konkrétních datových typů konkrétních délek.Coz je skvela vlasnost, kterou oceni kazdy programator a strasne pomohla uspechu C a C++.
...Rozlišovat můžete, ale bavíme se o jazyku C/C++. Jejich filozofie je taková, že se snaží být co nejefektivnější "assemblerem". Jazyk C/C++ je nějak postaven, a má nějaký standard. Dobrý programátor si přečte standard C/C++, a podle toho programuje. Pokud se vám něco ve standardu C++ nelíbí, standardizační komise ráda přijme vaše dobře zdokumentované návrhy včetně zdůvodnění. Nejspíše je asi zamítne, protože filozofie C++ je jiná než vaše myšlení, ale třeba jen maluji čerty na zeď. Bavit se se mnou, že byste si přál něco v C++ standardu jinak se mnou je ztráta času. Já jsem příliš malý pán na to, abych měnil standard C++.
Rozlišovat můžete, ale bavíme se o jazyku C/C++. Jejich filozofie je taková, že se snaží být co nejefektivnější "assemblerem". Jazyk C/C++ je nějak postaven, a má nějaký standard. Dobrý programátor si přečte standard C/C++, a podle toho programuje.Hezky uhybny manevr, ...
Pokud se vám něco ve standardu C++ nelíbí, standardizační komise ráda přijme vaše dobře zdokumentované návrhy včetně zdůvodnění.Mne je C++ uplne ukradene, ... tomu jazyku beztak neni pomoci, protoze je zapleveleny tolika balastem, protoze zpetna kompatibilita, a jedine vylepseni najde az v kremikovem nebi.
Hezky uhybny manevr, ...Vaše povídání o procesorech se nijak netýká C/C++. Je proto zbytečné se k němu vyjadřovat. Nemá to s ním žádnou souvislost. ---
Mne je C++ uplne ukradene, ... tomu jazyku beztak neni pomoci, protoze je zapleveleny tolika balastem, protoze zpetna kompatibilita, a jedine vylepseni najde az v kremikovem nebi.Ironií osudu je, že nemá náhradu. Proto je tu C++ s námi už několik dekád. Stále ještě nikdo nenapsal lepší programovací jazyk než je C++, jakmile je potřeba rychlost, efektivita, univerzálnost, samonosnost a obrovské rozpětí platform. Za těch několik dekád ho už tisíce zastánců jiných konkurenčních jazyků pohřbívalo. A C++ to nad nimi vyhrálo. Protože jak jsem napsal, C++ nemá ve svém účelu žádnou rozumnou konkurenci. Proto tu s námi je. I když se vám to nelíbí.
Vaše povídání o procesorech se nijak netýká C/C++. Je proto zbytečné se k němu vyjadřovat. Nemá to s ním žádnou souvislost.
Jejich filozofie je taková, že se snaží být co nejefektivnější "assemblerem".To povidani o instrukcich jsem tu zahrnul z toho duvodu, ze tvoje tvrzeni jsou znacne zavadejici, a prekypuji spis osobnimi urazkami nez fakty. Jeden by z toho mohl nabyt dojmu, ze uint16_t opravdu na rade RISCovych procesoru neexistuje.
Stále ještě nikdo nenapsal lepší programovací jazyk než je C++, jakmile je potřeba rychlost, efektivita, univerzálnost, samonosnost a obrovské rozpětí platform.C++ je nejlepší. Áno.
C/C++ nezaručuje existenci konkrétních datových typů konkrétních délek. ... Coz je skvela vlasnost, kterou oceni kazdy programator a strasne pomohla uspechu C a C++.Tato vlastnost obrovsky pomohla k úspěchu C/C++. Protože se rozšířila na astronomické množství platforem. Na každé platformě C/C++ vystaví typový systém nejvhodnější pro danou platfromu - a nejefektivnější pro danou platformu.
C/C++ nezaručuje existenci konkrétních datových typů konkrétních délek.Nemas celkom pravdu, co viem. Char je striktne 1 Bajt, ostatne maju definovany minimalny pocet bajtov.
Jenže bajt v C nemusí být osm bitů, viz konstanta CHAR_BIT
.
Datový typ uint16_t je podle C++ standardu "optional", tedy nemusí existovat.Coz je bajecna vlastnost stejne jako, ze nejsou presne definovany jednotlive typy a jejich chovani (napr. preteceni znamenkoveho typu). Treba (ne)znamenkovost a velikost typu char byva zdrojem docela zaludnych chyb. Hele, fakt nevykladej nic o tom, jak C/C++ ma vsechno presne definovane. Ale chapu, ze pokud se clovek venuje dlouhodobre astrologii, dokaze spravne predpovedet i to, s jakymi typy bude jeho program ve skutecnosti prelozen a neni potreba to uvadet ve specifikaci.
Existuje tehdy, a pouze tehdy, pokud procesor má přímý 16bitový typ.Mohu se laskave zeptat, co si pan hvezdopravec predstavuje pod pojmem procesor má přímý 16bitový typ?
Když potřebujete datový typ 16 bitů dlouhý, tak validní volba podle C++ standardu je uint_least16_t,Kdyz potrebuji napr. v hlavicce protokolu, v souborovem formatu, presne 16 bitu pro ulozeni, pouziji typ, ktery ma 16 bitu nebo vic... uff.
Hele, fakt nevykladej nic o tom, jak C/C++ ma vsechno presne definovane.C/C++ má poměrně dobře definované chování. To, že se to chování nelíbí deda.jablko je už jiný problém.
Ale chapu, ze pokud se clovek venuje dlouhodobre astrologii, dokaze spravne predpovedet i to, s jakymi typy bude jeho program ve skutecnosti prelozen a neni potreba to uvadet ve specifikaci.Někdy pochybuji o tom, jestli jste naprogramoval v životě alespoň hello world program. Už je to několikátá otázka od vás, kterou bych od skutečného programátora nečekal. Naprogramoval jste někdy vůbec něco?
Mohu se laskave zeptat, co si pan hvezdopravec predstavuje pod pojmem procesor má přímý 16bitový typMá dostatek strojových instrukcí, které umějí pracovat s 16bitovými hodnotami. Některé procesory prostě s 16bitovými hodnotami nepracují = nemají na ně strojové instrukce. Samozřejmě lze 16bitové oprace emulovat třeba jako práci se dvěma 8bitovými operacemi, ale není to zcela efektivní.
Kdyz potrebuji napr. v hlavicce protokolu, v souborovem formatu, presne 16 bitu pro ulozeni, pouziji typ, ktery ma 16 bitu nebo vic.Protože soubor je posloupností bajtů, tak použijete dva bajty. Mimochodem, donesla se k vám ta zpráva, že 16bitů může mít i rzný endian? A ne vždy se to může hodit do vaší struktury.
C/C++ má poměrně dobře definované chování. To, že se to chování nelíbí deda.jablko je už jiný problém.Dobre definovene choveni si predstavuji jinak. A patrne nejsem sam. To, ze v C/C++ jsou skalarni typy vyreseny fakt mizerne odrazi i to, ze to pozdeji vznikle jazyky tento pristup neprebiraji a definuji jednoznacne velikost typu a chovani v meznich podminkach.
Někdy pochybuji o tom, jestli jste naprogramoval v životě alespoň hello world program. Už je to několikátá otázka od vás, kterou bych od skutečného programátora nečekal.Nebyla to otazka, ale veta oznamovaci. Hlavne, ze sis kopl... jen trochu vedle.
Má dostatek strojových instrukcí, které umějí pracovat s 16bitovými hodnotami. Některé procesory prostě s 16bitovými hodnotami nepracují = nemají na ně strojové instrukce.Ty instrukce nejsou potreba. Napr. JVM nebo CIL nemaji instrukce pro aritmetiku s mensimi hodnotami nez 32bitu a vubec nicemu to nevadi.
Dobre definovene choveni si predstavuji jinak. A patrne nejsem sam.Znovu jen opakuji, co jsem už napsal: Chování je dobře definováno. Jen se vám nelíbí. ---
To, ze v C/C++ jsou skalarni typy vyreseny fakt mizerne odrazi i to, ze to pozdeji vznikle jazyky tento pristup neprebiraji a definuji jednoznacne velikost typu a chovani v meznich podminkach.Definice jednoznačné velikosti typu silně omezuje množství platforem, na kterých jazyk efektivně běží. Jazyk C/C++ chce běžet na každé myslitelné platformě efektivně. Chování typů v mezních podmínkách C/C++ obsahuje. ---
Ty instrukce nejsou potreba. Napr. JVM nebo CIL nemaji instrukce pro aritmetiku s mensimi hodnotami nez 32bitu a vubec nicemu to nevadi.Znovu se opakuji už podruhé nebo potřetí: C/C++ chce být EFEKTIVNÍM jazykem ve stylu přenositelného "assembleru". Jste snad hluchej, když vám už potřetí píší, že prostě filozofie C/C++ je mít PŘÍMO MAPOVANÉ TYPY do paměti a procesorových operací? Prostě toto je filozofie C/C++. S takovou filozofií byl C/C++ jazyk napsán. Má to své výhody i nevýhody. Já vím velice dobře, že emulovat můžete i to, co procesor nepodporuje. Mně to vysvětlovat nemusíte. Ale filozofie C/C++ je taková, že používá typy přímo podporované platformou. Tečka. Je váš subjektivní názor jestli je lepší to či ono. Howgh.
Chování typů v mezních podmínkách C/C++ obsahuje.Nejaky Ponkrac tu tvrdil, ze:
Dobrý programátor si přečte standard C/C++, a podle toho programuje.Z ceho plyne, ze nejaky Ponkrac neni dobry programator, protoze dle standardu: If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. Treba Java ma preteceni operaci jednoznacne definovane.
Jste snad hluchej, když vám už potřetí píší, že prostě filozofie C/C++ je mít PŘÍMO MAPOVANÉ TYPY do paměti a procesorových operací? Prostě toto je filozofie C/C++. S takovou filozofií byl C/C++ jazyk napsán. Má to své výhody i nevýhody.Se sluchem nemam problemy, ale kdyby ses zacal vyjadrovat rovnou k veci misto bezpredmetnych osobnich urazek, viz zacatek tohoto vlakna, diskuze by se vedla mnohem lip. Jedna vec je nejaka filozofie a druha vec je realna implementace v prekladacich, ktera se muze rozchazet s tvymi pocity, ze neco nejde a ze neco prekladace nedelaji.
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.Ano, to je jasně definované chování. Jediné možné, pokud chcete být platfromově univerzální. A jediné možné, pokud chce dosáhnout maximální rychlost. Jinak řečeno, pokud si to přečtete dále po této větě, C/C++ jsou určeny standardem a konkrétní platformou. To je jejich filozofie. ---
Treba Java ma preteceni operaci jednoznacne definovane.Také je na drtivé většině platforem velice neefektivní po všech stránkách. A na řadě platforem Javu nelze rozchodit vůbec. Zatímco C/C++ rozchodíte téměř na každé myslitelné platformě. A ten kód, který kompilátor vyprodukuje, bude efektivní. Já třeba budu programovat v C/C++ na STM32 vývojové desce a 16 KB RAM. Java se tam ani nenastaruje, ani si neuprdne. A přesně toto chtěli tvůrci C/C++. Naprosto univerzální, maximálně efektivní a úsporný jazyk. To je filozofie C/C++. To je něco, o čem se Javě nemůže ani snít. ---
Se sluchem nemam problemy, ale kdyby ses zacal vyjadrovat rovnou k veci misto bezpredmetnych osobnich urazek, viz zacatek tohoto vlakna, diskuze by se vedla mnohem lip. Jedna vec je nejaka filozofie a druha vec je realna implementace v prekladacich, ktera se muze rozchazet s tvymi pocity, ze neco nejde a ze neco prekladace nedelaji.Já jsem si myslel, že každý normální člověk chápe, že každá věc má svůj cíl, určení a filozofii. To samé platí i pro programovací jazyky. Po celou dobu jste argumentoval tak, že jste kritizoval, že bagrem najde doletět na Mars, a bagr má tu nevýhodu, že není růžovej. Celou dobu jste psal tak, jako že jste jeliman a nevíte, k čemu bagr slouží. Já jsem zbytečně psal dokola, že C/C++ má svůj účel, a k tomu je stvořen. A je stvořen jako báječný programovací jazyk, protože jsou tu s námi už 47 let. A stále neexistuje jiný programovací jazyk, který by se C/C++ v jejich dobrých vlastnostech dokázal vyrovnat. Pouze se objevují deda.jablko a další, co je kritizují, ale sranda je, že C/C++ nemají žádného soupeře, žádný konkurenční programovací jazyk, v nice, pro které jsou určeny. A to je nejlepší měřítko kvality návrhu těchto jazyků pro jejich účel.
Já třeba budu programovat v C/C++ na STM32 vývojové desce a 16 KB RAM. Java se tam ani nenastaruje, ani si neuprdne. A přesně toto chtěli tvůrci C/C++. Naprosto univerzální, maximálně efektivní a úsporný jazyk. To je filozofie C/C++. To je něco, o čem se Javě nemůže ani snít.Tak určitě; STM32-JAVA
Very small and efficient Java virtual machine:
- Flash: less than 30 KB
- RAM: less than 1.5 KB
- Startup time: less than 2 ms at 120 MHz
Pouze se objevují deda.jablko a další, co je kritizují, ale sranda je, že C/C++ nemají žádného soupeře, žádný konkurenční programovací jazyk, v nice, pro které jsou určeny. A to je nejlepší měřítko kvality návrhu těchto jazyků pro jejich účel.Rust je konkurencí už jen ze sociálního hlediska. Spousta lidí už má C++ plné zuby, což je myslím pěkně vidět i tady v diskuzi. Osobně můžu říct, že ve svém okolí vidím značný nárůst lidí, kteří používají Rust na místě, kde dřív C++. Osobně jsem pracoval pro společnost, která vzala svůj C++ kód a všechen ho přepsala do Rustu a všichni si to jen pochvalovali. Další pozice, kam jsem nedávno šel na pohovor jako Python developer to samé, na C++ už se mě ani nikdo neptal a rovnou je zajímalo jak jsem na tom s Rustem. Asi je pravda, že C++ je a ještě dlouho bude v některých věcech vyspělejší, ba dokonce i vhodnější. Nepřijde mi ale, že by to moc lidí zajímalo, protože obecně je to jazyk příjemný asi jako vytírání zadku šmirgl papírem. A user interface (což je v tomhle případě jazyk jako takový) se počítá. Nemyslím si že Rust někdy nahradí C++ ve smyslu že by byl všechen kód přepsán do C++, ale to že ho nahrazuje ve smyslu že lidi ho teď často používají na místech, kde by dřív použili C++ je tak nějak možné vidět všude kolem. Je otázka, nakolik je to jen móda.
Rust je konkurencí už jen ze sociálního hlediska. Spousta lidí už má C++ plné zuby
Nicméně rozhodovat se pod vlivem vzteku a jiných negativních emocí není zrovna racionální a obvykle to nedává moc dobré výsledky. Stačí se podívat na Go – to vypadá jako produkt lidí, kteří v první řadě nesnášejí C++, a to není moc dobrý výchozí bod. Je to takové odezdikezdi případně snaha dělat věci jinak, jen proto, aby se odlišili. Pak jsou tu výtvory lidí, jejichž motivem a nosnou myšlenkou je to, že nesnášejí Javu, nebo nesnášejí XML nebo nesnášejí SQL… to taky nedává dobré výsledky a místo evoluce to přináší jen negaci, opakování starých chyb a zanášení nových.
Rust mi oproti tomu jako negace C++ nepřijde, spíš trochu jako „C++ udělané správně“ (což mělo být tedy i D) akorát tomu pořád některé věci chybí a přeci jen je to ještě dost mladý jazyk.
Stačí se podívat na Go – to vypadá jako produkt lidí, kteří v první řadě nesnášejí C++, a to není moc dobrý výchozí bod.To se mýlíš, není to o tom, že by nesnášeli C++, oni nesnáší skoro všechny ostatní jazyky
Nepřijde mi ale, že by to moc lidí zajímalo, protože obecně je to jazyk příjemný asi jako vytírání zadku šmirgl papírem.Ta negativní emoce vychází z nějakých racionálních důvodů.
the behavior is undefined.Je jasne definovane chovani! A valka je mir! To uz je jak na tiskove konferenci s Jirim Ovcackem. Jasne definovane chovani je takove, ze pokud mam jeden zdrojovy kod a po prelozeni jej provedu se stejnymi daty, dostanu stejny vysledek. Ne, ze vysledek bude zaviset na tom jaky prekladac pouziji, s jakymi parametry, nebo snad na tom, jak se ten den prekladac nebo CPU vyspi. UB pro preteceni cisel neni kvuli efektivite, ale kvuli tomu, ze nejaka obskurni platforma muze pouzivat neco jineho nez dvojkovy doplnek. Dnes nejspis nic takoveho neexistuje, ale prekladace UB muzou pouzit k nezadoucim optimalizacim, coz pak muze byt zdroj nebezpecnych chyb.
Prozradim ti tajemstvi, presna definice toho, jak se ma chovat integer pri preteceni, vubec kod nezpomali, protoze je presne v souladu s tim, co se v dnesnich procesorech deje.Treba Java ma preteceni operaci jednoznacne definovane.Také je na drtivé většině platforem velice neefektivní po všech stránkách.
Já jsem zbytečně psal dokola, že C/C++ má svůj účel, a k tomu je stvořen. A je stvořen jako báječný programovací jazyk, protože jsou tu s námi už 47 let. A stále neexistuje jiný programovací jazyk, který by se C/C++ v jejich dobrých vlastnostech dokázal vyrovnat. Pouze se objevují deda.jablko a další, co je kritizují, ale sranda je, že C/C++ nemají žádného soupeře, žádný konkurenční programovací jazyk, v nice, pro které jsou určenyUz jsem to psal vys, davat rovnitko mezi C a C++ je znacne manipulativni. Zatim co C asi opravdu zustane jazykem pro systemove programovani, protoze se jedna o jednoduchy proceduralni jazyk blizky hardware, kde dela svou praci velmi dobre. U C++ bych si tim nebyl vubec jisty, protoze se jedna o jazyk neuveritelne komplexni, tezky na pochopeni a s velkym potencialem pro vznik chyb. Primou reakci na tyto problemy byl vznik Javy nebo C#. Tolik k te bezkonkurecnosti...
Zatim co C asi opravdu zustane jazykem pro systemove programovani, protoze se jedna o jednoduchy proceduralni jazyk blizky hardware, kde dela svou praci velmi dobre. U C++ bych si tim nebyl vubec jisty, protoze se jedna o jazyk neuveritelne komplexni, tezky na pochopeni a s velkym potencialem pro vznik chyb.
A čím to budeš v drtivé většině případů překládat? GCC nebo Clang? V tom případě tam podporu C++ máš – a teď je otázka, proč nepoužít některé vybrané funkce/vlastnosti C++, které ti usnadní práci. Argument proti tomu je: a) budu to chtít překládat i kompilátorem, který umí jen C nebo b) možnost používat C++ bude svádět programátory k tomu, aby občas použili něco z té temné stránky C++ a znepřehlednili tak kód a znesnadnili jeho údržbu.
Jak moc to jsou relevantní argumenty, si každý musí zodpovědět sám. Já ale C++ (resp. nějakou tu jeho rozumnou podmnožinu) považuji za celkem užitečný nástroj, když už musím dělat s nějakými C knihovnami – a pořád k nim mám přímý přístup a není tam nějaká mezivrstva.
A čím to budeš v drtivé většině případů překládat? GCC nebo Clang?A je to dulezite? Prekladac muzes napsat bez problemu v cemkoliv a z vlastni zkusenosti muzu rict, ze cokoliv je na psani prekladace lepsi nez C (popr. C++). Prekladac je v podstate jen funkce, ktera transformuje zdrojovy kod na binarni, pricemz vnitrne je to kompozice funkci, ktere transformuji jednu reprezentaci programu na druhou. Pokud ma jazyk prostredky, jak tyto transformace pohodlne popsat (typicky silny pattern matching) je psani prekladace mnohem komfortnejsi. Nedivil bych se, kdyby se casem objevil prekladac, ktery bude GCC/Clang konkurovat a nebude v C/C++. Ale takove veci se nestanou ze dne na den, protoze je to obrovska setrvacnost.
Já ale C++ (resp. nějakou tu jeho rozumnou podmnožinu) považuji za celkem užitečný nástroj, když už musím dělat s nějakými C knihovnami – a pořád k nim mám přímý přístup a není tam nějaká mezivrstva.Mozna by nebylo od veci zkontrolovat, jak se tebou zvolena "rozumna podmnozina" prekryva s tim, co nabizi treba ten Rust...
A je to dulezite? Prekladac muzes napsat bez problemu v cemkoliv a z vlastni zkusenosti muzu rict, ze cokoliv je na psani prekladace lepsi nez C (popr. C++). Prekladac je v podstate jen funkce, ktera transformuje zdrojovy kod na binarni, pricemz vnitrne je to kompozice funkci, ktere transformuji jednu reprezentaci programu na druhou. Pokud ma jazyk prostredky, jak tyto transformace pohodlne popsat (typicky silny pattern matching) je psani prekladace mnohem komfortnejsi.Myšlenka napsat překladač v např. pure FP jazyku je jistě lákavá, ale bude mít výsledek stejně dobrý space-time tradeoff jako implementace v C/C++? Umim si představit, že implementace v Haskellu by mohla zabírat třeba 2× ~ 4× víc paměti.
V tom případě tam podporu C++ máš – a teď je otázka, proč nepoužít některé vybrané funkce/vlastnosti C++, které ti usnadní práci.Protože je otázka, které to jsou, a je otázka, jestli se na tom lidi shodnou. Spousta lidí vyhodnotí, že ty benefity nevyváží (případné) problémy. Spousta lidí např. nemá rádo výjimky, IMO z celkem dobrých důvodů.
IMO z celkem dobrých důvodů.Z jakých mimochodem?
No, výjimky obecně jsou na širokou diskusi. Méně obecně - relevantněji pro tuto diskusi v kontextku staticky typovaných jazyků - jsem došel před časem k jednomu pozorování: Výjimky do staticky typovaného jazyka v podstatě vnášejí dynamické typování, konkrétně do signatur funkcí: Jakákoli funkce může "vrátit" (skrz throw mechanismus) libovolnou výjimku, která se pak chytá podobným způsobem, jakým se pracuje s typy v dynamických jazycích. Např. v Javě tento problém 'vyřešili' šalamounsky - tzv. "Checked exceptions". Na tomto řešení je vtipné, že už to v podstatě téměř výjimky nejsou, pouze to používá stejnou syntaxi jako výjimky a domnívám se, že by kdyby se používaly jen checked exceptions a běžné výjimky se vyhodily, dalo by se to implementovat bez mechanismu pro výjimky - prostě by kompilátor interně vygeneroval kód stejný jako pro ADT-based error handling. V C++ jsou exceptions specifications, což je demence, protože to kompilátor nekontroluje. Takže to je spíš jen taková dokumentace, která navíc přidává runtime overhead.IMO z celkem dobrých důvodů.Z jakých mimochodem?
nothrow
je lepší v tom, že nepřidává (nutně) overhead, ale furt je stejně dementní v tom, že to kompilátor nekontroluje a v případě, že letící výjimka narazí na nothrow
, tak prostě shodí program a čus.
No takže morál příběhu je, že IMO ve staticky typovaném jazyce víceméně nemají výjimky co dělat.
(Resp. ne v takové té běžné podobně, jak jsou třeba v C++, Javě apod., možná, že jsou jiné designy výjimek a/nebo specielní situace, kdy to může dávat smysl. Např. korutiny. Ale ani tam nebude od věci nějaká typová kontrola.)
No takže morál příběhu je, že IMO ve staticky typovaném jazyce víceméně nemají výjimky co dělat.
To právě záleží na tom, z které strany se na ně díváš. Když je bereš jako nějaké GOTO a skok někam do neznáma, tak je pochopitelné, že je vnímáš negativně. Ale když se na ně budeš dívat nikoli z pohledu technické implementace, ale z logického pohledu uživatele a budeš je brát jako součást kontraktu mezi autorem třídy/metody a jejím uživatelem, tak to smysl dává a do staticky typovaných jazyků to perfektně zapadá. Signatura ti pak jasně říká, že metoda vrací určitý datový typ a nebo v případě chyby vrací objekt reprezentující chybu, který má opět určitý typ (jeden konkrétní nebo jeden z pevně daného výčtu). A v Javě k tomu existuje i hezký syntaktický cukr, ve kterém snadno zapíšeš větve pro jednotlivé typy chyb (nemáš tam žádné instanceof a přetypovávání a naplní ti to objekt do proměnné daného typu) a který umožňuje RAII.
Na výjimkách je taky fajn to, že je nemusíš zpracovávat hned tam, kde vznikly, ale můžeš je (záměrně) poslat výš a určitý typ výjimek ošetřit na jednom místě.
Signatura ti pak jasně říká, že metoda vrací určitý datový typ a nebo v případě chyby vrací objekt reprezentující chybu, který má opět určitý typ (jeden konkrétní nebo jeden z pevně daného výčtu).Ano, ale pouze v případě Checked exceptions (jinak je typ dynamický)*, a pointa byla, že právě při použití Checked exceptions už ty výjimky nedávají moc smysl, protože to je už potom vlastně to samé co ADT errors, akorát v divným syntaktickým kabátě, který je daný pouze historickým vývojem (tj. tím, že Checked exceptions vznikly s non-checked exceptions). *) A ještě navíc tuším některé výjimky můžou jít okolo tohohle, jako třeba NPE.
A v Javě k tomu existuje i hezký syntaktický cukr, ve kterém snadno zapíšeš větve pro jednotlivé typy chybA nepřijde ti náhodou ten "hezký syntaktický cukr" nápadně podobný matchi z funkcionálních jazyků?
a který umožňuje RAII.V Javě možná, ale to je pouze limitace Javy. Obecně pro RAII nepotřebuješ ani tu syntaxi ani výjimky.
Ano, ale pouze v případě Checked exceptions (jinak je typ dynamický)
Dynamické výjimky právě moc v lásce nemám – přesně proto, že u nich člověk přichází o tu typovou kontrolu.
pointa byla, že právě při použití Checked exceptions už ty výjimky nedávají moc smysl, protože to je už potom vlastně to samé co ADT errors
A jak takovou chybu pošleš výš, když ji nechceš zpracovávat přímo tam, kde vznikla? Na výjimkách se mi právě líbí to, že se nahoru posílají implicitně, když je nezpracuješ (akorát ti kompilátor zkontroluje, že jsi tu výjimku deklaroval v signatuře metody, aby s ní ostatní mohli počítat), a pak taky to, že tím syntaktickým cukrem jasně vyznačují, kudy vede standardní tok programu a co jsou naopak výjimečné, nestandardní stavy a jejich ošetření.
A nepřijde ti náhodou ten "hezký syntaktický cukr" nápadně podobný matchi z funkcionálních jazyků?
Pattern Matching je obecnější princip. Pro ošetřování chyb mi přijde lepší syntaxe výjimek, protože z ní je na první pohled vidět, co je žádoucí a co nežádoucí stav (viz předchozí odstavec). Ale proti Pattern Matchingu nic nemám a v Javě třeba taky bude :-)
V Javě možná, ale to je pouze limitace Javy.
Tak Java je celá postavená na GC a princip RAII se tam dostal až o dost později, takže ta syntaxe není úplně ideální resp. musíš explicitně říct, že chceš RAII:
try (Zdroj z = získáníZdroje()) { práceSeZdrojem(z) }
a na rozdíl od C++ tam stoupá počet úrovní zanoření, ale jinak to v jazyku s GC asi moc nejde. Jinak souhlasím s tím, že s výjimkami to souviset nemusí (byť typicky to dává smysl právě kvůli zavření zdrojů po nějaké chybě) a používá se to i bez catch
/finally
.
A jak takovou chybu pošleš výš, když ji nechceš zpracovávat přímo tam, kde vznikla?Různé jazyky na to mají různé abstrakce. Funkcionální používají monády a Haskell má třeba do notation (což jestli tomu dobře rozumim je syntaxe pro kompozici monád do jedné větší monády). Rust má otazníkový operátor. Což je mimochodem silnější mechanismus než ty výjimky v tom, že umožňuje využít konverzi errorů jednoho na druhý, tj. když error E1 má definovanou konverzi na E2, tak může "vyhodit" výše error E1 ve funkci, která vrací E2. Zas je to horší v tom, že když chceš vracet víc různých errorů, potřebuješ pro to explicitní sumární typ. Což vyžaduje boilerplate kód. Určitě by to šlo vylepšit. Z mého pohledu tohle všechno jsou spíše detaily...
Pattern Matching je obecnější princip.Jistě, šlo mi o to, že ty
catch()
větve jsou prostě match, nic jiného to není.
Tak Java je celá postavená na GC a princip RAII se tam dostal až o dost později, takže ta syntaxe není úplně ideální resp. musíš explicitně říct, že chceš RAII (...) a na rozdíl od C++ tam stoupá počet úrovní zanoření, ale jinak to v jazyku s GC asi moc nejde.IMO s GC to v podstatě nesouvisí... Např. D má RAII i GC, Rust dřív mýval GC... V Javě by asi mohla např. existovat nějaká anotace pro proměnnou na stacku. Java kompilátor stejně určitě dělá escape analysis a interně asi tohle už nějak podporuje (hádám, ale přijde mi to pravděpodobný)...
Jistě, šlo mi o to, že ty catch() větve jsou prostě match, nic jiného to není.
Ano, jsou, ano, je to syntaktický cukr… a ano, přijde mi to užitečné (z těch důvodů, které jsem popisoval výše).
IMO s GC to v podstatě nesouvisí... Např. D má RAII i GC, Rust dřív mýval GC... V Javě by asi mohla např. existovat nějaká anotace pro proměnnou na stacku.
Je otázka, jak to udělat a nenabourat úplně koncepci toho jazyka, který je s GC od začátku spjatý. Přes anotace by to možná šlo… ale měly by se psát ke třídě nebo k proměnné? Pak je taky problém, co s výjimkami, které se objeví při zavírání zdroje – současné řešení s try {}
syntaxí tě donutí je ošetřit, kdežto anotace to udělat nemůže resp. bylo by to nekoncepční. Neříkám, že by se mi nelíbilo tam mít možnost RAII i bez těch zanořených závorek, ale moc mě teď nenapadá, jak to udělat.
Přes anotace by to možná šlo… ale měly by se psát ke třídě nebo k proměnné?IMO k proměnné. IMO ta escape analýza by měla být proveditelná, vzhledem k tomu, že Java ji dělá tak jako tak. Je teda pravda, že si nejsem jistej, na který úrovni se to děje - možná, že to dělá až JVM bytecode compiler...
Pak je taky problém, co s výjimkami, které se objeví při zavírání zdroje – současné řešení s try {}
syntaxí tě donutí je ošetřit, kdežto anotace to udělat nemůže resp. bylo by to nekoncepční.
Mně popravdě přijde ta praxe, kde close()
hází výjimky, dost pochybná. IMO od tohohle by měl být třeba flush()
nebo něco podobného.
Každopádně, s proměnnou lokální pro scope toho try
bloku (resp. obecně pro jakýkoli scope) by to mělo jít. Např.:
try {
local SomeResource resource = new SomeResource(argument);
resource.foo();
resource.bar();
} catch (Exception e) {
System.out.println("Ayyy, lmao...");
}
Jistě, šlo mi o to, že ty catch() větve jsou prostě match, nic jiného to není.V matchi ale musíš typicky ošetřit všechny stavy, ne? Kdežto výjimka co projde catchem automaticky putuje nahoru.
U výjimek je to taky explicitní, protože musíš přidat throws Výjimka
do signatury metody, kde tahle informace musí být tak jako tak, aby ostatní věděli, že odtamtud ta výjimka může vyletět. Akorát to máš na jednom místě a ne na dvou.
BTW: zajímavý by byl jazyk, který by šel rozšiřovat až na úroveň uživatelské změny syntaxe. Tzn. podporoval by např. jen pattern matching, ale umožnil by ti upravit si syntaxi (asi makrem?) tak, že by sis přidal vlastní konstrukci try (…) {…} catch {…} finally {…}
, kterou ten jazyk původně neobsahoval :-) Akorát tady je problém s tím, že podpora v IDE (nebo jen editorech zvýrazňujících syntaxi) by byla dost obtížná a taky by se to asi dost zneužívalo…
BTW: zajímavý by byl jazyk, který by šel rozšiřovat až na úroveň uživatelské změny syntaxe. Tzn. podporoval by např. jen pattern matching, ale umožnil by ti upravit si syntaxi (asi makrem?) tak, že by sis přidal vlastní konstrukci try (…) {…} catch {…} finally {…}, kterou ten jazyk původně neobsahovalTo afaik umí třeba ve vedlejší diskuzi zmiňovaný rebol. Osobně jsem toho ale nikdy moc nebyl fanouškem.Akorát tady je problém s tím, že podpora v IDE (nebo jen editorech zvýrazňujících syntaxi) by byla dost obtížná a taky by se to asi dost zneužívalo…
Akorát to máš na jednom místě a ne na dvou.Tak na dvou místech to musí být z definice, když se to na jednom konci definuje a na druhém odchytává
BTW: zajímavý by byl jazyk, který by šel rozšiřovat až na úroveň uživatelské změny syntaxe.No, tak to jsou takové ty všelijaké homoikonické jazyky... nebo případně v menší míře ten Haskell...
BTW: zajímavý by byl jazyk, který by šel rozšiřovat až na úroveň uživatelské změny syntaxe.To umí třeba TeX a je to peklo. To opravdu nechceš.
Spousta lidí např. nemá rádo výjimky, IMO z celkem dobrých důvodů.
Jenže jak to chceš řešit bez nich v „čistém“ céčku? Ty výjimečné situace z principu nastávají a musíš je nějak ošetřit a mj. pozavírat všechny zdroje, které jsi do té doby stihl otevřít.
Protože je otázka, které to jsou, a je otázka, jestli se na tom lidi shodnou.
Co takové RAII pro správu paměti a zdrojů? To mi v C++ přijde výrazně jednodušší a méně náchylné k chybám než to dělat ručně v C.
Já tedy souhlasím s tím, že Rust je lepší jazyk než C++ a pokud k tomu jsou nějaké výhrady1, tak to je řešitelné a časem to snad bude. Ale otázka je, když je tvoje výchozí pozice, že píšeš v C2, tak jestli je lepší úplně změnit jazyk a přidat tam další mezivrstvu, nebo zda raději nepoužít vybrané vlastnosti C++, které tvůj kompilátor tak jako tak podporuje. V druhém případě je to plynulý přechod a můžeš vlastně pořád psát v céčku a napojovat se přímo na OS a knihovny.
[1] chybějící standard, chybějící nezávislé implementace kompilátorů, chybějící nástroje…
[2] asi ne proto, že bys nějak moc chtěl, ale spíš kvůli knihovnám, které chceš použít
Teď třeba píši cadMousePro – nástroj pro konfiguraci myši, který používá knihovnu HIDAPI.
Protože jsem nechtěl s tím céčkovým API pracovat přímo, udělal jsem si tam vlastní1 mezivrstvu (pár tříd) v C++. Je pravda, že vytvoření téhle mezivrstvy vyžaduje nějakou práci a dalo by se to přirovnat2 k vytvoření mezivrstvy pro napojení v Rustu nebo třeba Javě (JNI, JNA). Jednodušší mi na tom přijde to, že je to celé v jednom jazyce, klidně by to šlo napsat i celé do jednoho souboru, a kompiluje se to jedním nástrojem. Na druhou stranu, u většího programu by se ta investice do další technologie asi vrátila – a tady mi vedle Javy přijde jako dobrá volba právě ten Rust (případně D, ale Rust vypadá živěji).
Jak by takhle malý program vypadal v Rustu? Jaké by tam byly praktické přínosy oproti C++? V současnosti se tam chystám dodělat D-Bus rozhraní a GUI, které se přes něj bude napojovat a tu myš ovládat. Takže tam nakonec bude i Qt (tudíž i C++), případně bych mohl použít GTK (tudíž C nebo C++), ale protože používám KDE, tak se mi víc hodí Qt.
Taky bych si to mohl zkusit napsat v Javě a volat tu C knihovnu odtamtud. Porovnání tří jazyků (C++, Rust, Java) by mohlo být celkem zajímavé.
[1] viz otázka v poradně: Návrhový vzor pro obalování C knihoven v C++
[2] co se týče pracnosti, ne technologie
Jednodušší mi na tom přijde to, že je to celé v jednom jazyce, klidně by to šlo napsat i celé do jednoho souboru, a kompiluje se to jedním nástrojem.To ale platí pro Rust taky. Já nevim, co maj lidi v téhle diskusi furt s nějakými mezivrstvami. Jediný rozdíl je, že v Rustu neuděláš
#include <foobar.h>
, místo toho si potřebuješ napsat nebo vygenerovat soubor s definicemi, tj. ekvivalent toho header file s Rust syntaxí. Tenhle file neobsahuje žádnou vlastní logiku, pouze deklarace funkcí a struktur, a kompiluje se normálně Rust kompilátorem, je to úplně normální Rust kód. Taky by se to dalo dát všechno do jednoho souboru.
Pro volání holého C API a používání třeba C pointerů je potřeba v Rustu unsafe
kód, ale to je doufám snad jasný a opět se jedná o standardní Rust kód kompilovaný normálně Rust kompilátorem.
Pro pohodlnější a bezpečné použití je dobrý si napsat wrapper - stejně jako v C++. Tyhle wrappery jsou to, o čem lidí mluví, když mluví o Rust bindingách, protože v Rustu prostě ten wrapper chceš mít prakticky vždy. Ale neznamená to, že to je nezbytně potřeba - když chceš, můžeš používat přímo holé C API stejně jako v C++.
Jak by takhle malý program vypadal v Rustu?Pro Rust zřejmě wrapper pro hidapi už existuje
Jinak aby bylo jasno, já se tě rozhodně nesnažím přesvědčit, že bys to měl psát v Rustu
Předesílám, že já se v tomhle vlákně taky nesnažím nikoho přesvědčit, spíš se chci něco dozvědět a třeba zjistit, na jaké úlohy by mi Rust byl užitečný, protože se mi celkem líbí.
To ale platí pro Rust taky. Já nevim, co maj lidi v téhle diskusi furt s nějakými mezivrstvami.
Jednak je to mezivrstva v tom smyslu, že když píšeš program v C/C++, tak ti stačí operační systém a GCC nebo Clang. Zatímco když píšeš program v Rustu, tak potřebuješ operační systém, Clang a navíc Rust (který na Clang/LLVM závisí). Takže tam máš o jeden prvek víc. Pro vývoj v Javě zase typicky potřebuješ OS + GCC + OpenJDK, což je stejný počet prvků jako v případě Rustu.
Nicméně tady jsem tou mezivrstvou myslel spíš ten „soubor s definicemi“ a „wrapper“.
když chceš, můžeš používat přímo holé C API stejně jako v C++.
Ale pořád si tam musím udělat ten extern { … }
a v něm vypsat signatury těch C funkcí, které chci používat, ne?
extern crate libc; use libc::{c_int, size_t}; #[link(name = "snappy")] extern { fn snappy_compress(input: *const u8, input_length: size_t, compressed: *mut u8, compressed_length: *mut size_t) -> c_int; fn snappy_uncompress(compressed: *const u8, compressed_length: size_t, uncompressed: *mut u8, uncompressed_length: *mut size_t) -> c_int; fn snappy_max_compressed_length(source_length: size_t) -> size_t; fn snappy_uncompressed_length(compressed: *const u8, compressed_length: size_t, result: *mut size_t) -> c_int; fn snappy_validate_compressed_buffer(compressed: *const u8, compressed_length: size_t) -> c_int; }
Ale souhlasím, že to není až taková tragédie. Z uživatelského hlediska je to na úrovni JNA v Javě, kde si zase uděláš rozhraní, které pasuje na ty C funkce, např.
public interface POSIX extends Library { public int chmod(String filename, int mode); public int chown(String filename, int user, int group); public int rename(String oldpath, String newpath); public int kill(int pid, int signal); public int link(String oldpath, String newpath); public int mkdir(String path, int mode); public int rmdir(String path); }
To je na použití taky jednoduché, akorát se to liší technicky v tom, že se tam používá libffi (ale v JNI to jde na přímo, bez libffi).
Pro Rust zřejmě wrapper pro hidapi už existuje
To existuje i pro C++, Javu a další jazyky, ale já jsem si to teď chtěl napsat sám, abych se na tom něco naučil a vyzkoušel si to.
A taky nevim, v jakým stavu jsou teď bindingy pro Qt. (Bindingy pro GTK jsou celkem slušný.)
Tohle je právě docela riziko. Pro Javu existuje Qt Jambi, které bylo svého času taky celkem slušné, ale dneska je pokud vím už neudržované (zřejmě ve stavu: „Known problems: Qt 5 support is still WIP“). Prostě jsi závislý na někom třetím, na kvalitě jeho práce a na tom, že to bude dlouhodobě udržovat. Na samotné Qt se asi dlouhodobě spolehnout dá, ale napojení na jiné jazyky psané nějakými jinými vývojáři je už takové nejisté. Napojení na knihovnu typu HIDAPI si klidně napíšu sám, ale psát si a udržovat napojení na Qt by se mi fakt nechtělo. Takže to GUI v Qt bych si dost možná napsal radši v C++ a s Javovským jádrem aplikace ho propojil přes nějaký soket nebo přes volání nativních funkcí.
Co takové RAII pro správu paměti a zdrojů? To mi v C++ přijde výrazně jednodušší a méně náchylné k chybám než to dělat ručně v C.S tímhle určitě souhlasím, ale poznámka: RAII a výjimky jsou ortogonální.
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.