#Klooienmetcomputers

Strings en slices

Arnout van Kempen over rommelen in een digitale wereld.

We zagen al dat variabelen van het type String vrij complex zijn. Ownership is hier van groot belang, omdat het een datatype is dat niet probleemloos op de stack kan worden geplaatst, maar als een dynamisch geheugenblok in de heap moet bestaan. En dan hadden we nog het verschijnsel van de string literal die niet van het type String is, maar &str.

Rust kent het verschijnsel slices. Dat is een deel van een array, of bijvoorbeeld een string (zoals in C een string ook eigenlijk een array van characters is, zo werkt het in Rust dus in feite ook). Als je in je code zegt:

let a = “Hallo”;
let b = “Wereld”;

dan bevat a niet de waarde "Hallo". De string zelf zit gewoon hard gecodeerd in je programma en wordt dus niet gekopieerd naar stack of heap. In a wordt alleen de referentie (te zien aan de &) naar de geheugenlocatie van “Hallo” geplaatst en de lengte van de slice. Want dat is wat a is, een slice. De gehele tekst in het geheugen is immers niet "Hallo", maar "HalloWereld". Alle literals worden gewoon achter elkaar in het programma-geheugen geplaatst en de variabelen bevatten een verwijzing naar een stukje van die string. Een slice dus.

Dat is op zich gewoon efficient met geheugen omgaan en alleen toepasbaar op string-literals. Maar wat moet je hier verder mee?

Herinner je de borrowing-rules en bedenk dat een slice dus een referentie is, want een & type, en dat dus sprake is van een verwijzing zonder ownership, een borrow dus. Pas de regels toe en je ziet dat Rust hier een stukje heel interessante bewaking toevoegt op compiler niveau.

Om dat goed zichtbaar te maken heb ik op GitHub een stukje code opgenomen dat fouten zal geven bij compileren. In de code wordt zichtbaar gemaakt hoe slices worden gemaakt, een beetje zoals we array-definities uit C kennen, met a[begin..eind]. 

Ook zien we dat de println!-macro probleemloos slices en strings hetzelfde behandelt. En dat we slices van slices kunnen maken en van strings. Mooi en makkelijk allemaal en het voelt vrij natuurlijk ook.

Maar het is de foutmelding van de compiler die het interessant maakt! De relevante code is:

let mut stekst = String::from(“Voorbeeldtekst in een String”);
let mut slice3 = &stekst[..];

Hier komt de eerste warning: slice is mutable, maar dat is nergens voor nodig, zegt de compiler. Waarom niet? Nou, dat volgt even later:

stekst = String::from(“Nu veranderen we stekst”);

Dit geeft een error, die misschien op het eerste gezicht niet voor de hand ligt. Immers, stekst is toch gedefinieerd als mut? Dat klopt, maar door gebruik te maken van from wordt een mutable borrow uitgevoerd. En dat mag niet, aangezien slice3 al bestaat. Zie de borrow rules. 

De slice is zelf een niet mutable borrow, dus andere slices of andere referenties zijn geen probleem. Maar muteerbare borrows zijn uitgesloten. En daarmee voorkom je rare verschijnselen. Want bedenk maar eens wat de waarde van slice3 had moeten zijn als stekst wel had mogen wijzigen. Onveranderd? Mee-veranderen? En zo ja, welke reeks dan? Nu is de reeks [..], maar de nieuwe string is korter, dus welke eindwaarde voor de slice? Kortom, gewoon afblijven, zegt Rust. 

En als we dan niet via String::from(“xxx”); hadden gewerkt? Dan houden we problemen. Een string kan je niet veranderen zonder een mutable borrow. En als we met een string-literal hadden gewerkt, hebben we een &str, dus een immutable borrow. Kortom, wat je ook bedenkt, Rust verbiedt je in de problemen te komen!

Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op github.com en zoek naar Abmvk/kmc. Het account Abmvk volgen kan ook. Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren.

Gerelateerd

reacties

Reageer op dit artikel

Spelregels debat

    Aanmelden nieuwsbrief

    Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

    Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.