To si myslím že je něco jiného - resp. vynecháním mut skutečně zabráním modifikaci vnitřku kolekce - ale mám k dispozici operace pro vytváření nových immutable struktur ze starých?
Tedy něco jako
let s1 = Set::empty()
let s2 = s1.add("foo")
let s3 = s2.add("bar")
let s4 = s3.remove("foo")
?
To myslím immutable variantami kolekcí (přičemž immutable kolekce by vůbec neměly mít metody upravující existující instanci kolekce, jen vytváření nových instancí ze starých, pokud možno s maximálním využitím structural sharingu, který je tímto umožněný)
ajo chapu, neco jako ma Haskell a Clojure. hmm to v std. knihovne Rustu na 90% neni, ale par lidi neco podobneho implementovalo https://github.com/Gankro/collect-rs/blob/2c724ca7631a792a1bc6fd6fa4f89f6f80b6bb3e/src/immut_slist.rs
Kdyz jsme u toho - pekne by bylo mit mapy a vektory ala Clojure (tj. interne to jsou "tluste" stromy), docela by to odpovidalo filozofii Rustu.
Prepacte len otazka od Javystu - no offense. Toto musi byt BRUTALNE neoptimalne. Nie je jednoduchsie urobit normalnu mutable kolekciu a potom ju 'zamknut' proti zmenam ak ju potrebujem vratit alebo poslat nejakemu neznamemu kodu? Pri kazdom add, remove kopirovat nejaku vacsiu kolekciu musi byt sialene.
Nie, nestretol som sa s FP prvy krat. Len to je jeden z dovodov preco to povazujem za neoptimalne. V krajine zazrakov kde mame neobmedzenu kapacitu pamate, neobmedzeny stack a neobmedzeny vypoctovy vykon by vsetci robili v LISP-e. Ale nerobia. To iste plati pre Rust. Ked zahodim moznost optimalizacie a nabozenstvo 'cistoty jazyka' zvitazi nad praktickostou niet uz pomoci. Neviem ako daleko to dotiahol Rust, dufam ze nie prilis smerom k 'uplnej FP cistote'.
Rust sice ma nekolik FP vlastnosti, ale v zadnem pripade to neni cisty FP jazyk. K tomu ma zatim porad nejbliz Haskell.
Jinak v LISPu se nedela z jinych duvodu, trosku si za to lispari muzou i sami, ze za tech >40 let nedokazali prijit s praktickym standardem (Scheme je akademicke, Common Lisp zase obrovska bestie ;) Mozna Clojure...?
pisou tam:
"After escape analysis, the server compiler eliminates scalar replaceable object allocations and associated locks from generated code. The server compiler also eliminates locks for all non-globally escaping objects. It does not replace a heap allocation with a stack allocation for non-globally escaping objects."
takze na zasobniku to porad referencni typy alokovat neumi?
Ve zkratce, pokud mas referencni typ a prislusny objekt nikam neunika (tzn. nepotrebujes ani na nej referenci), je mozne tento objekt rozbit na jednotlive atributy a ty alokovat v ramci stack frame dane metody. Takze objekt jako takovy neni alokovan (a to ani na heapu), ale je neprimo umisten na stack.
Oboji pristup ma svoje pro a proti. Pokud je kolekce immutable, tak je jistota, ze ji muzes pouzit ve vic vlaknech naprosto bez jakychkoli obezlicek typu zamku, semaforu a z toho vyplyvajicich problemu na HW urovni. Navic pokud je kolekce navrzena dobre (klasicky list, Clojure vektory nebo mapy), tak pouziva structural sharing. Je za tim i urcita filozofie, ze jakakoli hodnota (i kolekce) predstavuje 'otisk' nejakeho objektu v case a tudiz musi byt immutable - stejne jako nema smysl mutovat 2 na 3, tak to plati o dalsich typech. Rich Hickey o tom ma par prednasek.
Na druhou stranu asi aplikace kreslici do obrazku bude mit mutable bitmapu, to je asi jasny :-)