Pořád se nemohu ubránit pocitu, když se snažím sledovat vývoj jazyků, že tyto nové jazyky (go, rust) jsou na půli cesty mezi C a C++.
C -> (go, rust) -> java -> C++
A proto, jakákoliv snaha pochopit tyhle jazyky pro mne znamená snížit se na úroveň myšlení, kde jsem byl před 10-15 lety. Mí přátele znají můj názor, který by se dal jednoduše vyjádřit větou: "na to se vykašlete a naučte se pořádně C++"
(no flame)
Gorutiny, kanály, koherentní syntax s přímou podporou pro věci, jako jsou seznamy, vícenásobné vratné hodnoty, automatickou typovou inferenci (postupně se do C++ zavádí, ale Go jde dále, i když samo o sobě je v tomto bodě dost primitivní), integrovanou správu balíků, velmi rychlou kompilaci, která umožňuje Go používat i jako v podstatě skriptovací jazyk, apod.
U věcí jako je garbage collector a duck typing se nedá říct, že je "postrádá", protože u některých problémů představují výhodu a u jiných naopak nevýhodu. Nicméně tam, kde jsou žádoucí, je tím pádem Go lépe vyhovující jazyk.
C++20 nedožene jednoduchost a programátorskou produktivitu, jakou nabízí Go. Stejně tak nedožene typový systém Rustu a statickou prokazatelnost, kterou tento umožňuje. Dohnat takovéto vlastnosti není možné, pokud to má zůstat C++.
Což samozřejmě neznamená, že by C++ nemělo taky svoje výhody a silné stránky jak proti Go, tak proti Rustu. Ale je absolutní blbost tvrdit, že jím vývoj v oboru programovacích jazyků na věky skončil a od té doby je všechno jenom jakási náhražka pro ty, co se nedokáží naučit C++.
Tak především když pronášíte takovéto generalizace o Go a Rustu, tak to svědčí o tom, že je moc neznáte, protože oba tyto jazyky jsou koncepčně úplně jiné a kladou si naprosto odlišné cíle. Mluvit o tom, jak si údajně stojí "Go a Rust" nemá o mnoho větší smysl, než mluvit obecně o "Javě a Fortranu".
Dále ten údajný názor "vašich přátel" by se dal přirovnat k tvrzení, že nemá moc velký smysl se zabývat věcmi, jako je Cairo a Vulkan, lepší je se pořádně naučit xlib
Jazyk, ve kterém by nebylo nic, co by se mi nelíbilo, jsem jaktěživ neviděl, ačkoli kdyby mi někdo chtěl tvrdit, že takovým jazykem má být C++, tak se na to vykašlu a půjdu radši pást kozy
O D se taky trochu zajímám, i když pro něj v hobby projektech nemám použítí. Kdo hledá přímou náhradu za C++, pro toho je D dneska možná ideální volba a navíc i částečně zpětně kompatibilní. Bohužel na výsluní se už asi nedostane. Dlouho trpěl problémy na úrovni komunity (dvě různé, nekompatibilní "standardní" knihovny), má omezený ekosystém a novější jazyky, jako právě Go, Swift a Rust už jsou ve svých nikách vývojově zase někde jinde.
Já si osobně nemohu pomoci, ale go, rust, javu apod. bych neskládal mezi C a C++, spíš do samostatné větve (začínající v C, ale nekončící v C++). V mnohých ohledech mi nové jazyky (teď spíše mluvím o C# a Pythonu, se kterými mám víc zkušeností, než javou (už je to dávno) či go a rustem (žádné)) přijdou (ve srovnání s C++) jeden krok vpřed a dva do strany (myšleno negativně).
Posledních pár let pracuji primárně v C# a zrovna poslední rok mám na starosti kód, který má být dost výkonný v reálném čase (o čemž bych mohl klidně napsat rozsáhlý silně hate článek) a v podstatě je mi celý jazyk překážkou, než pomůckou (pro tento účel). (Na přepnutí do C++ je dávno pozdě.)
Na druhou stranu ale jednoznačně uznávám, že jestliže neřeším každou milisekundu, ale mám jich pár volných (toto není nadsázka), tak implementace C# (často řádově násobně pomalejší, než v C++) dostačuje a vývoj je výrazně rychlejší a tedy levnější. A pohodlnější. A umožňuje tedy i víc/rychleji/snadněji experimentovat s různými řešeními. Tedy to, co bych potřeboval, je jazyk, který má rychlost vývoje odpovídající javě/C#, ale s možností se přepnout do „výkonného módu“ na úrovni C++. A unsafe C# je (s přihlédnutím na integraci se „safe“ C#) hluboko pod čistým C.
Navíc C++ má spousty vlastních problémů (často z historických důvodů + zpětné kompatibility, občas celkem nešťastné rozhodnutí), takže jako vývojář bych si hrozně moc přál něco jako ++C (C++ 2). Který by se poučil s řešení moderních jazyků, ale vyhnul se jejich problémům. Už jenom ta tendence psát si vlastní „STL“, kterou v jiných jazycích nemám, o čem vypovídá (a rozhodně nejsem sám).
C# dejme tomu patří celkově do podobného směru, jako Go (myšleno ve smyslu orientace na síťové služby a business aplikace, GC, filozofie zaměřená na snadnou použitelnost atd) ale přiznám se, že snažit se ho používat na RT kód by mě nenapadlo ani ve zlém snu. Totéž platí o Go. Rust je úplně jiná kapitola a pro aplikace tohoto typu naopak exceluje, možná, že právě v něm byste nalezl vhodného nástupce C++. Na druhou stranu psát v něm web službu nebo nějakou aplikaci používající SQL backend je jen pro otrlé masochisty, to snad už i v samotném C++ by to byl menší opruz!
20. 9. 2019, 08:41 editováno autorem komentáře
„ale přiznám se, že snažit se ho používat na RT kód by mě nenapadlo ani ve zlém snu“
Ne vždy si může člověk vybrat, v čem se bude dělat...
„Totéž platí o Go.“
A přitom gorutiny - aspoň, jak jsem je pochopil - umožňují daleko efektivnější využití CPU, než co jsem viděl jinde. Když si v jiném jazyce vytvořím frontu úloh a spustím N vláken (N = počet jader), ale přitom některé čekají na pomalejší zdroj (např. HDD)...
Z diskuze začínám mít dojem, že bych měl upřesnit, že výrazem „mám na starosti kód, který má být dost výkonný v reálném čase“ nemám na mysli „kritickou real-time aplikaci“, ale když už, tak „soft real-time“ (tedy nestihnu není konec světa, ale není to ani dobře).
(Což samozřejmě nic nemění na problémech, které GC nebo výše zmíněný nedeterminismus gorutin přináší.)
Co přesně myslíte tím “nedeterminismem gorutin”? Ty jsou přece rozvrhovány kooperativně a tedy deterministicky (na rozdíl od preemptivních vláken) a čekají jen na vnější podněty (zámky, síť, disk...).
A jaké problémy přináší GC? Ten má v Go někde od verze 1.5 minimální latenci a téměř se neprojevuje (na tom má zásluhu hlavně alokace většiny objektů na zásobníku díky pokročilé escape analýze). Upřímně by mě zajímalo, na jaký problém jste v Go v souvislosti s GC narazil.
Jinak v RT (včetně soft) se alokuje veškerá paměť na začátku a později už se na haldu nesahá (ať už jazyk používá GC nebo explicitní alokaci), ovšem jak jsem psal, v Go je to jedno, není-li problémem latence v řádu 100 μs.
Viz https://www.root.cz/clanky/programovaci-jazyk-go-pro-skalni-ceckare/nazory/#o1027611. Já osobně zkušenosti s go nemám žádné (takže jej nehodnotím), jen mi přišlo, že diskuze částečně může vycházet z určitých předpokladů, tak jsem je chtěl upřesnit a zároveň jsem chtěl vyjádřit, že tím nijak neoponuji výše odkazovanému názoru.
Aha, tak to bylo nedorozumění. Jinak ten odkazovaný “názor” je nebetyčná blbost.
Co se týče .NET (potažmo C#), kritické (řekneme RT) věci se dají řešit přes C++/CLI, kde má člověk plnou kontrolu nad alokací a zároveň nepotřebuje (relativně pomalé) P/Invoke. Kdysi o této kombinaci vyšla obsáhlá bichle zaměřená na high frequency trading. Tím neříkám, že bych .NET na něco takového použil, ale pokud už do toho člověk zabředne, může to být jediné schůdné řešení (a poměrně rozumné, zvlášť dnes v době C++17).
Není to blbost, natož nebetyčná. Jednoduchý příklad (převzatý a pozměněný z A Tour of Go):
package main
import (
"fmt"
"time"
)
func main() {
for k := 0; k < 20; k++ {
go func() {
fmt.Println("running")
for {}
} ()
}
timer1 := time.NewTimer(2* time.Second)
<- timer1.C
fmt.Println("Timer 1 expired")
timer2 := time.NewTimer(time.Second)
go func() {
<- timer2.C
fmt.Println("Timer 2 expired")
} ()
stop2 := timer2.Stop()
if stop2 {
fmt.Println("Timer 2 stopped")
}
}
Prvních 20 gorutin cykluje naprázdno, samozřejmě je to simulace nějakého dlouhého výpočtu, který plně využívá všechna jádra a všechna vlákna na úrovni OS. Následuje soft-RT část. Když si to pustíte, uvidíte, že čekání na timery bude trvat různě dlouho a někdy (u mě často) se nedočkáte nikdy, protože runtime je plně vytížen stávajícími gorutinami. Neboli je nutné programovat kooperativním způsobem se všemi složitostmi, co to obnáší. Netvrdím, že v Go není v tomto případě možné dosáhnout žádoucího výsledku, tvrdím, že gorutiny soft-RT aplikace nijak neusnadňují, naopak jsou zdrojem problémů.