díky za výborný seriál. Rust je velice dobře navržený jazyk. Akorát nejsem schopen se vymotat z pekla hlášek "cannot borrow immutable field as mutable", "cannot move out of borrowed content" apod. Vím, že něco na toto téma se řešilo už ve druhém díle, stejně, stačí mi v projektu dvě struktury s metodami a nehnu s tím :-(
Doporučuju začít u "oficiální" dokumentace https://doc.rust-lang.org/stable/book/ a taky http://rustbyexample.com/ a tady jsou dost vysvětlené lifetimy https://doc.rust-lang.org/nomicon/. Ono to vůbec není tak složité jak to vypadá a spoustu těch věcí člověk podvědomně používá i v C++ aniž by si to uvědomoval.
Ja bych vypichl toto pravidlo, ktere hodne pomuze s beznymi problemy, na ktere jako Cckar a Javista narazim. V Rustu "nemennost" pri prirazovani ci predavani znamena;
You may have one or the other of these two kinds of borrows, but not both at the same time:
one or more references (&T) to a resource,
exactly one mutable reference (&mut T).
Jinak on vetsinou prekladac napise nejenom KDE je chyba, ale i kontext, ve kterem nastala. To je strasne fajn, protoze ti rekne "nemuzu pouzit tento objekt na radku 10", "ownership tohoto objektu byl presunut na radku 8"
Jo, Rust (a Cargo) je výborný systém. Jak se správou projektu, tak chybové hlášky při kompilaci.
Ten můj problém se mi podařilo lépe identifikovat (ve větším projektu jsem si nebyl jist co to způsobuje) a asi jde o to, že se snažím měnit prvek struktury. Ale jak v tomto případě z něj udělat mutable (a jestli to je řešení) to asi ještě budu muset pátrat.
error[E0502]: cannot borrow `self.messages` as mutable because it is also borrowed as immutable
--> src/main.rs:21:17
|
18 | match self.messages.get(0) {
| ------------- immutable borrow occurs here
...
21 | self.messages.push("empty list".to_string());
| ^^^^^^^^^^^^^ mutable borrow occurs here
22 | }
23 | }
| - immutable borrow ends here
error: aborting due to previous error
struct Module {
name: String,
messages: Vec<String>,
}
impl Module {
fn new(name: String) -> Module {
Module {
name: name,
messages: Vec::new(),
}
}
fn print(&mut self) {
match self.messages.get(0) {
Some(msg) => {}
None => {
self.messages.push("empty list".to_string());
}
}
let messages = self.messages.join("\n");
println!("Module {}\n{}", self.name, messages);
}
fn add_message(&mut self, msg: String) {
// let fst_msg = self.messages.get(0);
self.messages.push(msg);
}
}
fn main() {
let mut module = Module::new("Main".to_string());
module.add_message("first message".to_string());
module.print();
println!("Hello, world!");
}
To je jednoduché a není to jen o Rustu: self.messages.get(0) je nejspíš refernce na první prvek vektoru. Předpokládám, že vektor se na push() může přealokovat do jiné části paměti (tak jako v C++), protože zaručuje, že jsou prvky v paměti uložené za sebou. Tím pádem push zneplatní refenci na libovolný prvek vektoru (i v C++). Buď je potřeba hodnotu zkopírovat, nebo je potřeba použít jiný kontejner. (Záleží co od toho kontejneru vyžaduješ, a u kterého kontejneru ti Rust dovolí append když držíš referenci na prvek. To bohužel nevím, protože vše o Rustu vím jen z tohoto seriálu.)
Ked uz tu robite tutorial na Rust co tak naprogramovat v nom nejak 3d engine a potom nejaku jednoduchu FPS hru, a nie len vypisovat pismenka do konzoly? Je kopec ludi ktori bavi programovanie ale okrem volani destruktoru chcu viediet aj prakticky use case nie len zoznam zakladnych keywordov ved tie sa nauci kazdy staci si pozriet manual. Takto vela zaujimavych vlastnosti jazyka nevynikne lebo pri vypisovani hello worldu si ich clovek neuvedomi pritom rust je prave jazyk urceny na low level veci.
No popravde by to asi malokdo, kdo zacina v Rustu, na 3d enginu dal, ony i takove malickosti jako vektory a matice musi resit ownership, takze se zaklady musi vysvetlit tak jako tak. Ale zkusim popremyslet, bindingy na OGL existuji, takze by neco slo dat dohromady. S tim seznamem keywordu to bylo mysleno jak?