Na forum 4programmers.net korzystamy z plików cookies. Część z nich jest niezbędna do funkcjonowania
naszego forum, natomiast wykorzystanie pozostałych zależy od Twojej dobrowolnej zgody, którą możesz
wyrazić poniżej. Klikając „Zaakceptuj Wszystkie” zgadzasz się na wykorzystywanie przez nas plików cookies
analitycznych oraz reklamowych, jeżeli nie chcesz udzielić nam swojej zgody kliknij „Tylko niezbędne”.
Możesz także wyrazić swoją zgodę odrębnie dla plików cookies analitycznych lub reklamowych. W tym celu
ustaw odpowiednio pola wyboru i kliknij „Zaakceptuj Zaznaczone”. Więcej informacji o technologii cookie
znajduje się w naszej polityce prywatności.
Łooo panie, ile kodu. Nawet traity implementujesz. Jest sens implementować traity jak i tak nie potrzebujesz polimorfizmu? (Chyba że potrzebujesz, tylko okiem z komórki rzuciłem). Ja wiem że w OOP się trzecie te interfejsy i klasy czy jest to potrzebne czy nie (wyjątkiem jest chyba tylko Kotlin) ale czy w Ruscie tez jest taka konwencja?
Shalom
Sugerujesz ze napisałem kod w Javie, który tylko udaje że jest Rustem? To jest całkiem możliwe :P
Łooo panie, ile kodu. Nawet traity implementujesz. Jest sens implementować traity jak i tak nie potrzebujesz polimorfizmu?
Gdzie te implementacje traitów? impl Cośtam { ... } to nie jest implementacja traitu. Implementacja traitu to raczej coś a'la impl TraitName for StructName { ... }.
Można wstawić #[derive(Clone, Copy, Debug, Eq, PartialEq)] przed struct czy enum i mieć za darmo implementacje różnych traitów, pod warunkiem, że wszystkie pola też mają (rekurencyjnie) implementacje tych traitów. Szczegóły: https://doc.rust-lang.org/rust-by-example/trait/derive.html
P.S. Copy to tylko do bardzo lekkich struktur. Do czegokolwiek nietrywialnego należy użyć Clone. Różnica jest taka, że kopiowanie jest niejawne, automatyczne, a klonowanie jest jawne, więc widać gdzie ponosimy koszt klonowania.
Różnica między Copy i Clone jest jeszcze na innym poziomie - Copy jest wyłącznie do kopiowania płaskich wartości, które można skopiować kopiując obszar pamięci jednym ciągiem (czyli przez memcpy). Nie da się zrobić głębokiego Copy schodzącego głębiej poprzez referencje. Zauważ, że Copy to tylko marker, nie ma żadnych metod.
Chciałem dziś zrobić ładnie z .fold() ale kopiowanie boarda po oznaczeniu pola strasznie się ślimaczyło, a nie umiem przekonać borrow-checkera do jakiegoś:
ale w sytuacji kiedy mark_line nie zwraca kopii Board tylko &Board
edit: Żeby wyjaśnić o co pytam. Można by napisać taki kod:
Kopiuj
useitertools::Itertools;structBoard{
board:Vec<i32>,}implBoard{fnnew(size:i32)->Board{returnBoard{ board:(0..size).map(|x|0).collect_vec()};}fnmark_field(&self, index:usize)->Board{returnBoard{
board:self.board
.iter().enumerate().map(|(i,&value)|if i == index { value +1}else{ value }).collect_vec()};}}pub(crate)fnsolve(){let board =(0..10000).fold(Board::new(10000),|board, index| board.mark_field(index));println!("{}", board.board[1]);}
Czyli za każdym razem kiedy robimy mark_field zwracamy nową planszę. Tylko że jak plansza jest duża to nagle robi sie to bardzo wolne, z oczywistych względów.
I teraz zastanawiałem się, czy można tak zrobić, zeby nasze mark_field zwracało zmodyfikowaną początkową tablicę, a nie tworzyło nową za każdym razem (pytanie co jest "bardziej rustowe" i moze jest jakaś trzecia opcja?). I pisząc tego posta doszedłem do tego, ze mogę zrobić:
Tak, to prawda. Ale wtedy zamiast fold robisz proste iterowanie z akumulatorem, co jest IMHO bardziej rustowe. Rust ma mechanizmy pozwalające bezpiecznie mutować i nie należy na siłę robić z niego Haskella. fold zaciemnia sytuację, bo właśnie sugeruje że dostajesz coś nowego, a tu chcemy po prostu zmodyfikować jeden istniejący obiekt.
Hmm dość specyficzny język. Moim zdaniem miejscami mocno autystyczny, kiedy np. nie możesz porównać &int z intem i musisz robić jakiś cyrk w stylu &0. Dodatkowo nie wyobrażam sobie pisania w Ruście bez silnego wsparcia IDE, które pokazuje wyniki inferencji typów, szczególnie kiedy nagle po jakimś .iter() czy w jakimś .map() dostajesz &&X.
Swoją drogą, biorąc pod uwagę brak raw-pointerów jako takich (w sensie jakiegoś int* ptr = 0x12345; w C), zastanawiam się, czemu składnia idzie w kierunku pointerów z C (w kontekście & i *) a nie czegoś na wzór referencji.
Shalom
Na co dzień to Java/Python
Shalom
Nie no w pracy raczej nie będę miał okazji użyć nigdzie rusta, a przynajmniej nie przewiduje :D
Dodatkowo nie wyobrażam sobie pisania w Ruście bez silnego wsparcia IDE, które pokazuje wyniki inferencji typów, szczególnie kiedy nagle po jakimś .iter() czy w jakimś .map() dostajesz &&X.
To może być przyzwyczajenie javowe - zupełnie niepotrzebne natręctwo do podglądania typów. Podobny problem niektórzy raportują w kotlinie... podczas kiedy całkiem dobrze się pisze z wyłączonymi hintami typów. W haskellu to norma, że typów nie widzisz przez całe długie kawałki kodu i zwykle żadnego specjalnego wsparcia IDE nie ma.
A rust z wnioskowaniem typów jest bliżej nawet tego haskella.
@jarekr000000 może gdyby były jakieś naturalne koercje pomiędzy tymi & to by się dało, ale kiedy nie możesz porównać &int z intem, a gdzieś nagle dostajesz & albo w ogóle && to moim zdaniem jednak ciężko.
Swoją drogą, biorąc pod uwagę brak raw-pointerów jako takich (w sensie jakiegoś int* ptr = 0x12345; w C), zastanawiam się, czemu składnia idzie w kierunku pointerów z C (w kontekście & i *) a nie czegoś na wzór referencji.
@Shalom pisanie przez parę lat w C++ skłoniło mnie do konkluzji, że implicit referencje to zło wcielone. Semantyka wskaźników używana w C czy Javie jest prosta i skuteczna. To, że w zależności od kontekstu referencja zachowuje się jak wskazywany typ albo nie powoduje dużo problemów np. nieustanne niepotrzebne kopie, konieczne cuda na kiju (jak std::reference_wrapper) popieprzone wyłomy w systemie typów. Zauważ, że w wielu przypadkach Rust idzie na rękę i sprawia, że referencje są przezroczyste w przypadkach, gdy jest to całkowicie nieszkodliwe np. wołanie metod.
Shalom
czy Javie ? Przecież w Javie masz właśnie ładne "niewidzialne" referencje i nigdy nie ma potrzeby robienia ręcznej dereferencji.
ale nie masz też "normalnych" wartości (oprócz prymitywów, ale te z drugiej strony nie mają referencji/pointerów), więc wprowadzanie dereferencji nie ma sensu.
Fundamentalną różnicą jest to, że w C++ da się zaimplementować swap(x, y) a w C/Javie nie.
Shalom
Wydaje mi się że jednak twój problem z referencjami w C++ wynika z mutowalności, co akurat w Ruście nie jest problemem bo tam musisz explicite oznaczyć coś jako mutable.
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.
Shalomp_agonShalom