Cél és előfeltétel
Egy függvénynek gyakran nem az számít, hogy az adat tömbből vagy más tárolóból érkezik, hanem az, hogy milyen elemeket láthat. A szelet egy összefüggő részre adott kölcsönzött nézet. Saját elempuffert nem hoz létre, ezért a forrás hozzáférési szabályai továbbra is fontosak. Ebben a leckében a részhalmaz kijelölését és a határok kezelését teszed tudatossá.
Előfeltétel a megosztott és kizárólagos kölcsönzés, továbbá a tömbök és indexelés. A különálló edition 2024 programok a megadott adatokon futnak, külső bemenet nélkül. Előbb rajzold fel a kiválasztott tartományt, és írd le, hány elemet vársz; csak utána ellenőrizd a tényleges szeletet.
A nézet hossza futás közben is változhat
Egy háromelemű tömb típusa tartalmazza a hármas hosszt. Az egész számok szeletreferenciájának típusában viszont nem rögzítjük a konkrét elemszámot. Ugyanaz a függvény így két, öt vagy nulla elemről is számolhat összeget. A hossz ettől még létezik, csak az adott nézet adata, nem a függvény aláírásának rögzített száma.
Az üres szelet érvényes bemenet lehet. Összegzésnél a nulla természetes eredmény, de az első elem lekérdezésénél már hiányt kell kezelned. A szelet nem varázsol elemet az üres helyre, és nem oldja fel a határok szabályait. A függvénynek előre ki kell mondania, hogy az üres adat mit jelent: értelmes eredményt vagy külön jelzett hiányt.
A tartomány két széle
A kezdő index beletartozik a szokásos szelettartományba, a felső index nem. Egy egytől három előtti helyig kijelölt rész ezért két elemet lát: az egyes és kettes indexűt. A felső határ lehet a teljes hossz, mert ott már nem elemet olvasunk, hanem az utolsó elem utáni vágási határt jelöljük ki. Ez fontos különbség az egyetlen elem indexeléséhez képest.
A közvetlenül létrehozott hibás tartomány pánikolhat. Ha a határok nem biztosak, a get tartományos változata opcionális nézetet ad. Az üres, de érvényes tartomány és a hibás tartomány eltér: az előbbiből lehet Some üres szelettel, az utóbbiból None. Ezeket nem célszerű ugyanarra az üres adatlistára mosni, ha a feladatnak fontos a hibajelzés.
A szövegszelet UTF-8 nézet
A szövegszelet típusa a str referencia. Stringből és szövegliterálból is kaphatunk ilyet, így olvasó függvényeknél sokszor ez az általánosabb paraméter. A nézet az eredeti szöveg érvényes részére mutat, a betűk nem másolódnak külön pufferbe. A forrás nem semmisülhet meg addig, amíg a belőle kölcsönzött nézetet használjuk.
A szöveges tartomány indexei bájthatárokat jelölnek, nem emberi betűsorszámokat. Egy ékezetes betű több bájtot is elfoglalhat. A közepén történő vágás érvénytelen UTF-8 rész lenne, ezért a biztonságos get None eredményt ad. Nem fogunk tetszőleges betűszámhoz önkényes bájtindexet rendelni. A későbbi Unicode lecke részletesebben megvizsgálja, hogy a bájt, a skalárérték és a látható karakter miért külön fogalom.
1. feladat: ugyanaz az összegző több nézeten
Írj függvényt, amely egész számok szeletreferenciájából összeget számol. Hívd meg a teljes tömbbel, annak középső két elemével és egy üres résszel is. A bemeneti tömb legyen egy, kettő, három és négy. A számok kicsik, ezért az összeg nem csordul túl; a feladat központja a kiválasztott nézet.
Megoldás
fn osszeg(adatok: &[i32]) -> i32 {
let mut eredmeny = 0;
for &adat in adatok { eredmeny += adat; }
eredmeny
}
fn main() {
let adatok = [1, 2, 3, 4];
assert_eq!(osszeg(&adatok), 10);
assert_eq!(osszeg(&adatok[1..3]), 5);
assert_eq!(osszeg(&adatok[2..2]), 0);
assert_eq!(adatok, [1, 2, 3, 4]);
}
A hívások mind ugyanazt a függvényt használják, külön másoló kód nélkül. Az üres tartományhoz tartozó nulla az összegzés választott szerződésének része.
2. feladat: érvényes üres és hibás tartomány
A háromelemű tömbből kérd le a teljes nézetet, az utolsó elem utáni üres nézetet és egy túl hosszú tartományt. Mindegyikhez get hívást használj. A három eredményt külön vizsgáld, ne alakítsd át automatikusan a hiányt üres adattá. Ezzel az egyetlen elem lekérdezésekor látott opcionális eredményt tartományokra is alkalmazod.
Megoldás
fn main() {
let adatok = [10, 20, 30];
assert_eq!(adatok.get(0..3), Some(&[10, 20, 30][..]));
assert_eq!(adatok.get(3..3), Some(&[][..]));
assert_eq!(adatok.get(0..4), None);
}
A teljes hossz helyén álló vágási határ érvényes. Ugyanitt egy elem közvetlen lekérése már a tömb után járna; a két művelet jelentése eltér.
3. feladat: biztonságos szöveges vágás
A „kör” szövegből kérd le az első betűt és az ö betűt tartalmazó nézetet a megadott UTF-8 bájthatárokkal. Külön vizsgáld meg az ö közepén végződő tartományt. A feladat ezekre a konkrét adatokra kéri a határok ellenőrzését; nem általános, minden szónál működő betűkivágó algoritmust készítünk.
Megoldás
fn main() {
let szo = String::from("kör");
let nezet: &str = &szo;
assert_eq!(nezet.len(), 4);
assert_eq!(nezet.get(0..1), Some("k"));
assert_eq!(nezet.get(1..3), Some("ö"));
assert_eq!(nezet.get(0..2), None);
assert_eq!(szo, "kör");
}
Az eredeti szöveg tartalma nem változik. A hibás vágás nem egy fél betűt ad vissza, hanem hiányt jelez, így a program megőrzi az érvényes szöveg feltételét.
Elfogadási feltételek
- Az összegző teljes, részleges és üres nézeten rendre tíz, öt és nulla eredményt ad.
- A hossz helyén kijelölt üres tartomány érvényes, a tömbön túlnyúló tartomány hiányt jelez.
- A „kör” ékezetes betűjének közepén végzett vágás get eredménye None, az eredeti String változatlan.
Továbblépés
A kölcsönzött adatokkal már másolatok nélkül tudsz dolgozni. A structok és metódusok leckében nevet adsz az összetartozó mezőknek, majd a hozzáférés jogát az adott művelethez választod meg.