Variabelen en constanten
Arnout van Kempen over rommelen in een digitale wereld.
Om Rust te leren gebruik ik https://doc.rust-lang.org/book/title-page.html als basis, aangevuld met ChatGPT, YouTube en eigen probeersels.
Wat Rust direct al wat raar maakt, is hoe de taal met variabelen en constanten omgaat. Een constante in Rust lijkt nog het meeste op een macro in C, die je daar met een #DEFINE maakt. In Rust kan je constanten definiëren waar je wil, maar voor de hand liggend is dit buiten de functie-definities te doen, zodat de scope globaal is. Conventie is een naam te geven in hoofdletters, je moet een type opgeven en de waarde mag uitsluitend bestaan uit simpele berekeningen die op het moment van compileren kunnen worden uitgevoerd. Gebruik van variabelen in de waardetoekenning is dus niet toegestaan. In de source die ik op GitHub zette staat een simpel voorbeeldje:
const BYTES_PER_64K: u32 = 64 * 1024;
Even verderop wordt de waarde van de constante geprint en van de constante minus 1. Let op dat printen van een waarde zonder berekening tussen de {} mag plaatsvinden, met berekening moet het gebeuren na de string, net als in C. Dus wel
println!(“{BYTES_PER_64K}”);
println!(“{}”,BYTES_PER_64K-1);
maar niet
println!(“{BYTES_PER_64K-1}”);
Waar Rust vreemd wordt, is met de variabelen. Een variabele in Rust is standaard niet muteerbaar, dus in feite een constante, behalve dan dat het geen constante is. Als vanzelf spreekt wat het type van de variabele is, is het niet nodig die op te geven. Wel moet de variabele gedeclareerd worden, met de opdracht let. Als je wil dat een variabele muteerbaar is, of mutable, dan declareer je met let mut.
Dus dit gaat fout:
let x = 1;
x = x + 1;
en dit gaat goed:
let mut x = 1;
x = x + 1;
Maar het kan nog gekker. Je kan een non mutable variabele wel gebruiken om een nieuwe variabele met dezelfde naam te maken en een waarde te geven. Dit proces heet shadowing, omdat de nieuwe variabele de oude als het ware in de schaduw zet en onzichtbaar maakt. Dus dit werkt weer wel:
let x = 1;
let x = x + 1;
Door opnieuw let te gebruiken, wordt een nieuwe x gedeclareerd en wordt niet de oude x van een nieuwe waarde voorzien.
Als je shadowing toepast binnen een scope, overleeft de nieuwe variabele het einde van de scope niet, en komt de oude variabele uit de schaduw te voorschijn.
let x = 1; // x is nu 1
{ // nieuwe scope
let x = 2; // x naar de schaduw, nieuwe x is 2
} // einde scope, x overleeft niet
println(“{x}”); // oude x uit de schaduw, is dus 1
Shadowing heeft een ander bijzonder effect, het type van de nieuwe variabele mag afwijken van het type van de oude variabele.
Dit gaat goed:
let spaties = “ “; // type van spaties is string
let spaties = spaties.len() // type van spaties is numeriek
Dit gaat fout:
let mut spaties = “ “; // type van spaties is string
spaties = spaties.len(); // numeriek past niet in string
Wat is dit voor gekkigheid? Waar C je tot in het krankzinnige dingen laat doen, die ook krankzinnig fout kunnen gaan, eist Rust een grote nauwkeurigheid in bedenken wat je exact wil gaan doen. C compileert bijna alles en ontploft in je gezicht. Rust doet enorm moeilijk tijdens compileren, maar levert vervolgens wel foutloze code op. Dat is de gekkigheid hier.
Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op www.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
De basis van de 8080: registers en de ALU
Arnout van Kempen over rommelen in een digitale wereld.
De basis van de 8080: pinnen en interrupts
Arnout van Kempen over rommelen in een digitale wereld.
De lijst der lijsten
Arnout van Kempen over rommelen in een digitale wereld.
Van 4004 naar 86-64
Arnout van Kempen over rommelen in een digitale wereld.
We gaan diep!
Arnout van Kempen over rommelen in een digitale wereld.