Je to přesně tak, ale tady se střetávají tři věci:
1) pole má indexy prvků v rozsahu 0 až délka-1
2) array.len() vrací délku, takže prvek array[array.len()] už neexistuje
3) ALE současně range generuje hodnoty v rozsahu start <= x < end, takže "i" nikdy nebude rovno array.len()
Takže program:
fn main() { for i in 0..10 { print!("{} ", i); } }
Vypíše:
0 1 2 3 4 5 6 7 8 9
neboli bez desítky.
To je v pohodě :-) Zkusím potom napsat shrnutí - krátkej článek s ukázkami a odkazy na konkrétní kapitoly v seriálu.
Mimochodem, range takto funguje i v dalších jazycích, což je někdy fajn, někdy to trošku štve, ale zdá se to být dost konzistentní.
Python:
>>> range(0,10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Clojure:
user=> (range 0 10) (0 1 2 3 4 5 6 7 8 9) user=> (range 10) (0 1 2 3 4 5 6 7 8 9)
Ve vetsine programovacich jazyku se pouzivaji spis polootevrene intervaly, protoze se s nima lepe pracuje (viz tento priklad), a predejde se tak mj. i fencepost problemu. Priklad s Pythonim range() ktery generuje take polootevrene intervaly:
len(range(m)) == m
len(range(a, b)) == b - a
range(a, a) == []
range(a, b) + range(b, c) == range(a, c)
Asi by to mělo patřit pod první díl, ale chtěl bych se autora zeptat, co si myslí o následujícím článku: Rust vs. Go. Nejde mi o nějaký boj mezi těmito jazyky, ale spíš o názor na závěrečné kapitoly a jejich zhodnocení člověkem, který už Rust zná a prošel si úvodními fázemi seznámení s jazykem. Děkuji.
to je trosku prehnane ne?
tady ten borec v diskusi to mozna trefil: "Go is becoming a success. And I think ultimately, you *hate* that. You want it to fail. Its very existence is an affront to everything you hold dear. If Go were to become a success, it would somehow invalidate all your past successes and efforts."
to asi nekdy citime vsichni, kdyz si jen uvedomim, kolik "effortu" jsem v poslednich 15 letech ztratil technologiemi, ktere se proste neprosadily nebo rovnou umrely... (a to se snazim vyhybat frontendu, tam se to meni snad kazdej pulrok :)
Nojo IT se v některých oblastech skutečně mění rychle (třeba ten zmíněný front-end, protože došlo k dost radikální změně v použití počítačů - už nejenom PC, ale hlavně client-server), na druhou stranu jsou pořád oblasti, které jsou velmi konzervativní. Často se zmiňuje finančnictví s COBOLem, ale je toho víc, oblast MCU a vůbec embedded věcí, řídicí jednotky, viděl jsem i dost složité a drahé přístroje s DOSem (vlastně proč ne) apod.
Trošku odlehčeně napsáno, berte hodně s nadsázkou: http://tmikov.blogspot.cz/2015/02/you-dont-like-googles-go-because-you.html
Ten clanek mi prijde takovy pochybny (napriklad odkazovani na 3 roky starou a vyresenou issue).
Jako pokus o objektivnejsi srovnani Go vs Rust mi prije toto:
https://medium.com/@robertgrosse/my-experience-rewriting-enjarify-in-rust-723089b406ad#.uukigyil8
https://medium.com/@robertgrosse/parallelizing-enjarify-in-go-and-rust-21055d64af7e#.7vrcc2iaf
Jak jsem psal, nejde mi o nějaké "hate" porovnání. Napsat, že je to pochybný článek, je přehnané. Jedná se o respektovsného autora respektovsného produktu, který rozhodně umí programovat. Každopádně dělal poměrně zodpovědnou analýzu a zatímco v přípravné fázi Go téměř vyřadil, v přímém testování zase špatně dopadl Rust (z pohledu složitosti). Proto mne zajímá názor člověka, který Rust dobře zná.
To je velmi zajímavé srovnání a Andrei má v mnoha věcech pravdu. Taky v tom, že o případném úspěchu či neúspěchu mnohdy rozhoduje "značka", ať už nějaký populární lídr nebo fakt, že daný jazyk prosazuje známá IT firma (s tím, že nemáme informace o tom, jaké je skutečné zastoupení jazyka v té firmě).
Já bych s tím, že populární značka prosazuje - nesouhlasil. Ani to nemá oporu v tom, které programovací jazyky se prosadily v průměru za poslední desetiletí.
Prosadit programovací jazyk je extrémně těžká věc - chce to jednak jazyk implementačně dotáhnout do prakticky použitelného stavu, dále dlouhodobá podpora. Zároveň rozumně navržený jazyk a popis standardu. To je náročná práce na 10 let a více - a podle historie to většina "známých značek" vzdá dříve, protože jejich motivace není obětovat se pro prosazení jazyka. Navíc firmy mají většinou jiné cíle, než dopilovat jazyk.
Google i Mozilla navíc jsou extrémně krátkodobé v podpoře čehokoli. Obě rázně a bez milosti neustále řadu projektů ukončují, často i populárních, a proti vůli uživatelů.
Klidně si tipnu, že Go a Rust budou patřit do těch technologií, o kterých se nyní mluví, že převálcují svět a budou tu na věky věků, ale za pár let po nich pes ani neštěkne, a většina IT si ani nebude vzpomínat, co to vlastně bylo - a budou tipovat, že Go a Rust byla značka žvýkačky, limonády nebo něco podobného.
Schválně se uložte tento můj komentář a přečtěte si ho za dva roky. Uvidíte, jak směšný bude v roce 2019 názor "Ten borec to možná trefil: Go is becoming a success. And I think ultimately, you *hate* that."
Každý rok slyšíte o mnoho technologiích, které převálcují svět, a po 99 % z nich za rok dva ani pes neštěkne. Go ani Rust nemají ani 1% šanci, že budou úspěšnými - a budou něčím jiným než krátkodobým štěkem. Zabijí je samy autorské právnické osoby, které je stvořily.
"Já bych s tím, že populární značka prosazuje - nesouhlasil. Ani to nemá oporu v tom, které programovací jazyky se prosadily v průměru za poslední desetiletí."
to asi záleží na tom, kde bereš informace o nasazení (či prosazení popř. popularity) jazyků. Asi každý má svůj žebříček podle toho, co se používá v jeho okolí. Já tam ale docela korelaci vidím - C# je asi jasnej (ano je starší než zmíněných deset let, mluvíme ale o prosazení), tandem Objective C a Swift podle všeho přesně kopíruje míru prosazování jejich lídrem (ObjC mírně klesá, Swift roste), dále tam máme Go, VB.NET (nojo no, Tiobe to tak vidí :-). Za všemi stojí nějaká firma. Na druhé straně spektra je Python a trošku klesající C, C++, Javu.
1) TIOBE index není o prosazení, ale o tom, jak moc se o daném jazyku žvaní na internetu. Když v nějakém programovacím jazyce bude uděláno milión důležitých programů/projektů, a nikdo o nich nenapíše na internetu, nebo jen pár tisíc stránek - bude to z hlediska TIOBE propadák. Tedy TIOBE je pro mě je zcela irelevantní pro to, o čem píši - tedy pro to, jestli se jazyk používá, a jestli přežije - a dále věřím jen statistice, kterou jsem si sám zfalšoval, jak údajně říkal jeden významný chlapík.
2) Mluvil jsem o prosazení schválně za poslední desetiletí. Protože dříve byla situace jiná. Dříve naopak korporace mohly a také často úspěšně jazyky vyvíjely a prosazovaly.
3) Jak moc se programuje v ObjectiveC mimo Apple hardware? U Shiftu totéž? Kolik znáte programů pro Linux/Windows/cokoli v ObjectiveC či ve Swiftu?
4) Je úplně jedno, jestli C/C++/Java/atd. klesá či roste - všechno už několik desetiletí přežívá, a nejspíše ještě řadu desetiletí přežije. Chvíli na vrcholu, chvíli v pozadí, pak zase na vrcholu, ale je tu pořád. Krátkodobé trendy jsou k ničemu.
5) To, o čem jsem psal je, že celá myriáda jazyků, jejichž prvotní motivace a idea byla "zničit C/C++", jako je Go, Rust, D, a další - budou za historicky krátký čas zcela neznámé, a vyhynulé.
6) Jazyky tvořené "známými značkami" mají tu vlastnost, že jejich vyhynutí nejde dost dobře zabránit, jakmile korporace o ně ztratí zájem. Pokud se toho ujme jednotlivec, korporace mu veslo nepředá, aby kazyk zachránil. A když už jazyk vyhyne, obvykle už ho jednotlivec, který chce zasvětit život jeho záchraně, už ho nevzkřísí, neboť je pozdě. Všichni už si zvykli, že je konec a přeorientovali se.
S bodem 1 souhlas, každý máme svoji statistiku. Jen na okraj: TIOBE to má ve skutečnosti vychytanější, protože reflektuje i nabídky/poptávky programátorských jobů, takže to taky o něčem vypovídá. Mj. tam díky tomu mají i COBOL, což je dosti uzavřená komunita. Tito lidi většinou nemají důvod blogovat či psát články o COBOLu, už vůbec ne na net :-) A taky to je trošku sebepotvrzující se proroctví, protože docela dobře vím, že TIOBE semtam sleduje management velkých firem.
Body 4 a 6 si odporují, příkladem je Java.
Až u bodu 5 jsem pochopil, proč jsi napsal ten první komentář. Ale to není žádný boj, nedejbože nějaká svatá válka proti C/C++. Minimálně Go a Rust tak prezentovány nejsou (D možná jo, už jen jménem).
Tak v podstatě má pravdu, jen bych asi dodal dvě věci k tomu, že přechod na Rust je skutečně těžší:
1) to, že je Rust prezentován jako náhrada C v _určitých_ typech aplikací neznamená to, že si céčkový programátor sedne a začne hned psát funkční a bezpečný kód. Rust je skutečně dosti odlišný, jak syntaxí (to je po chvíli maličkost), tak i sémantikou, ale tato změna asi byla nutná. Na druhou stranu jsou hlášení překladače skutečně dobré, zejména v porovnání s některými překladači C++.
2) vlastní základní knihovny Rustu se rozšiřují pomalu, protože se autoři snaží je udělat dobře na první pokus (což, pokud se to povede, je jen dobře). Ovšem musí se za to platit - í poměrně základní věci jsou řešeny v externích knihovnách, takže se většinou neobejdete bez použití Carga (já se tomu zatím snažím v článku vyhýbat, ale za chvíli nebude zbytí :-)
V článku se bohužel neřešila výkonnost aplikací, takže nevíme, jestli vůbec požadují rychlost Rustu nebo jestli by třeba nestačil managovaný jazyk.
Popravde mam pocit, ze pouziti poli bude asi dost omezene, mozna to tak vyzaduje prekladac, aby vzdycke presne znal delku. Jestli to chapu dobre z tutorialu, tak vektory (vec!) jsou alokovany na heapu a jsou menitelne (pridani prvku napriklad). U poli by me asi vadila ta divna inicializace pres unsafe - to nejde nejak obejit (potom by to bylo ok)?
neni nekde prehledne porovnani array s vec?
V Rustu je podmínka pro alokování na stacku že datový typ musí mít známou velikost, array tohle splňuje. Alokovat na heapu se dá pomocí Boxu ( Box::new([0; 10])
), takže alokace na stacku není podmínkou. Data vektoru jsou vždy na heapu.
Vec má dynamickou velikost, array fixní. Kde se krásně setkávají jsou právě ty řezy (slice): řez na Vec je stejný typ jako řez na array.
fn increment_all(slice: &mut [i32]) {
for i in slice.iter_mut() {
*i += 1;
}
}
fn main() {
let mut array = [0, 1, 2, 3];
let mut vec: Vec<_> = (0..4).collect();
increment_all(&mut array);
increment_all(&mut vec);
println!("{:?}", array); // [1, 2, 3, 4]
println!("{:?}", vec); // [1, 2, 3, 4]
}
Ohledně toho unsafe, Rust považuje neinicializovanou paměť za unsafe a nedá se vytvořit array s neinicializovanými prvky bez unsafe bloku.
Když si například napíšu:
fn main() {
let mut a = [1,2,3,4,5,6];
let mut b = &a[3..4];
b[1] = 10;
}
tak kompilátor zařve, že cannot assign to immutable indexed content `b[..]`
Není to moc jasné - a je mutable, b je (asi) mutable reference na slice, tak proč nemůžu přes b změnit prvek v a? Podle https://www.root.cz/clanky/prace-s-poli-v-programovacim-jazyku-rust/#k06 je slice stejně jen ukazatel + délka a v céčku něco podobného udělat jde prakticky stejně (kromě délky).
Problém je v tom, co je vlastně na let mut b = &a[..]
mutabilní. b je zde mutabilní proměnná držící typ &[i32]
, tedy nemutabilní referenci na řez polem. Takže b můžeme přiřadit jakoukoliv jinou hodnotu typu &[i32]
, ale nemáme mutabilní přístup k hodnotám pole.
let mut b = &a[2..6];
println!("{:?}", b); // [2, 3, 4, 5]
b = &b[1..];
println!("{:?}", b); // [3, 4, 5];
Naproti tomu let b = &mut a[2..6]
nabízí řez polem s mutabilním přístupem, ale samotné proměnné b nelze přiřadit jinou hodnotu typu &mut [i32]
.
let mut a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
{
let b = &mut a[2..6];
b[2] = 0;
println!("{:?}", b); // [2, 3, 0, 5]
}
println!("{:?}", a); // [0, 1, 2, 3, 0, 5, 6, 7, 8, 9]
aha, takže let mut b ... znamená jen to, že do toho b můžu později přiřadit jiný slice, vůbec to nesouvisí s tím, co přiřazuji?
Jinak díky, takto to valí (v předchozím příkladu byla chyba a[3..4] vrací jednoprvkový slice, takže žádné b[1] neexistuje, sorry)
fn main() {
let mut a = [1,2,3,4,5,6];
let mut b = &mut a[3..5];
b[1] = 10;
for i in b.iter() {
println!("{}", i);
}
}
[psal jsem uz rano, ale prispevek asi nekde ceka na schvaleni :) takze zkusim znovu]
Jaka je vlastne vyhoda poli (array) oproti vektorum? Ja zatim vidim jen lepsi kontrolu prekladace a mozna to, ze se pole mohou alokovat na zasobniku a ne na heapu. Ale treba uz udelani pole s ruzne dlouhymi radky asi jednoduse nejde ne? neni tedy lepsi vzdycky pouzit vektory (tam predpokladam stejne rychly pristup, tj. index*sizeof prvek nebo neco podobne efektivniho, zadne prochazeni seznamem). Me vlastne u poli zarazil kod s unsafe, to vypada dost hnusne popravde receno :)
Pokud to dobre chapu, tak pole ani nejde porovnavat, protoze Eq trait (a dalsi) plati jen pro velikost max. 32 prvku.