Wpis z mikrobloga

Ależ to jest durne:

a := []int{1, 2, 3, 4, 5}
lo, hi := a[:2], a[2:]
lo = append(lo, 6, 7, 8) // Ojoj, zamazuje `lo[2:5]`!
fmt.Printf("%v %v\n", lo, hi) // Wypisuje `[1 2 6 7 8] [6 7 8]`

#golang #programowanie

Jak Wy w tym możecie programować?
Przecież przy tym PHP to dobrze zaprojektowany język.
  • 13
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

  • 2
Dla odmiany Rust zachowuje się przyzwoicie:

let a = [1, 2, 3, 4, 5];
let (lo, hi) = a.split_at(2);
let lo = lo.iter().chain(&[6, 7, 8]).collect::<Vec<_>>();
println!("{:?} {:?}", lo, hi);
  • Odpowiedz
@Krolik: do składni można się przyzwyczaić chociaż mi jakoś nie siada. Ale zastanawia się dlaczego ludzie w ogóle wybierają do projektów ten język skoro on się niczym nie wyróżnia
  • Odpowiedz
  • 1
@walokid: Ale mnie nie chodzi o składnię. Składnia w językach to pikuś. Mnie chodzi o semantykę.
Masz slice, dopisujesz do niego nowe elementy na końcu, a inny slice zostaje nadpisany. Cholernie niebezpieczne i raczej mało kto się tego spodziewa. Jeśli już, to bardziej spodziewałbym się że "spooky action at a distance" może nastąpić w wyniku modyfikacji elementów slice'a, a nie dopisania nowych.

Ale zastanawia się dlaczego ludzie w ogóle
  • Odpowiedz
  • 0
@kontra: ależ ja świetnie rozumiem jak działa wskaźnik. Tylko że w Go to nie jest zwyczajny wskaźnik. Problem powstał bo wcisnęli koncept wskaźnika oraz kontenera w jedną rzecz (slice) i dorzucili magię w postaci append. W efekcie powstał dziwoląg który ani nie jest dobrym wskaźnikiem ani nie zachowuje się jak przystało na grzeczny kontener. Zauważ że ani C ani C++ ani Rust nie mają tego problemu mimo że też posiadają
  • Odpowiedz
@Krolik:

ależ ja świetnie rozumiem jak działa wskaźnik


Zalinkowalem, bo wygladasz na zaskoczonego, ze wziales wskaznik, zmieniles pare wartosci w sasiednich adresach, a nastepnie zdziwiles sie, ze wartosci w sasiednich adresach sie
  • Odpowiedz
  • 0
@kontra: zaskoczenie jest stąd że masz dwa osobne (różne) wskaźniki na logicznie rozłączne obszary pamięci, ale poprzez wykonanie operacji append, która w innych językach jest bardziej charakterystyczna dla kontenerów / kolekcji a nie wskaźników nagle pojawia się aliasing (zazębianie obszarów) którego wcześniej logicznie nie było. Tzn. był, ale był właśnie perfidnie ukryty, bo slice o długości 2 wcale nie oznacza obszaru pamięci o długości 2, tam jest jeszcze ukryte capacity
  • Odpowiedz
@Krolik: Zgadza sie. Rozumiem troche dlaczego moze to sie zdawac dziwne, no ale tak jak mowie - ktokolwiek klepie w Go dobrze rozumie czym sa slices i jak ta konkretna implementacja slices dziala, dlatego w normalnych okolicznosciach taki blad raczej nie mialby miejsca, szczegolnie ze mowimy o subslices, czyli poniekad wskazniku na wskaznik. Osobiscie jak uczylem sie Go i ogarnalem takie zachowanie o jakim mowiesz to jakos nie bylem szczegolnie
  • Odpowiedz