Reflexionen über die Programmiersprache Rust 16

in #deutschlast month

*Typumwandlungen

In gewisser Weise wollte ich dieses Thema wohl immer etwas umgehen. Aber was solls, jetzt bin ich da. Vermutlich lerne ich gleich wieder einiges dazu.
Also, um was gehts? Typumwandlung heißt den Datentyp wechseln. Wozu kann man so etwas brauchen? Beispielsweise, wie früher schon mal erzählt, verwendet der bekannte ASCII Code ein Alias an Zahlen statt Buchstaben. Dadurch lassen sich die Zahlen des ASCII von 0-255 durch-iterieren. Damit fangen wir an.

fn main() {
    for mut x in 0..=255{
        let convert:char = x.into();
        print!("{}.{}\t",x, convert);
        x+=1;
    }

Ausgabe

image.png

Mit .into lässt sich hier also ein u8 in einen char verwandeln. Es gilt auch als die sichere Umwandlungsmethode. Warum das so ist, muss ich selbst mal genauer nachschauen, denn verstanden habe ich es noch nicht. .into gilt auf jeden Fall als eine implizite Methode. Im Gegensatz gilt as (was wir noch nicht kennen) als explizite Methode. Eins as Beispiel sieht so aus:

let a:u8 = 42;
    let b: f32 = a as f32;
    let c = 4.5;
    let d = c/b;
    println!("{}:{}={}",b,c,d);

Ausgabe

image.png

Im Prinzip hätten die ersten 2 Codezeilen gereicht. Allerdings wäre es ungünstig für die Beweislage gewesen, denn die Printn!-Anweisung gab nur 42 für b aus und es war nicht erkennbar, dass es sich tatsächlich um ein float handelt; jetzt aber schon.

Um zum Thema implizit und explizit, bzw. darauf zurückzukommen, warum .into, sauberer ist als as. .into ist ein trait. Das ist ein Thema auf das werden wir noch kommen, es kann aber doch noch etwas dauern. Aber man kann zumindest sagen, dass ein trait, viele Regeln und Kontrollinstanzen beinhaltet. Vielleicht sollten wir absichtlich mal etwas fehlerhaft arbeiten, um es zu verdeutlichen.

let a:u16 = 350;
let b:u8 = a as u8;
println!("{}",b);

Ausgabe
image.png

Jetzt möchte man glatt sagen: "Huch, was ist denn da passiert?" Es lässt sich leicht aufklären und zeigt damit auch die Schwäche von as (wenn es nicht so beabsichtigt war). Die u8 haben eine Bereichsgrenze von 0..255. 350 ist eindeutig darüber. Es fängt also bei 255+1 wieder bei 0 an. Deshalb 94.

Oder noch eines:

let a:f32 = 3.1415;
let b:u8 = a as u8;
println!("{}",b);

Ausgabe
image.png

Hier wird einfach die Kommazahl (PI) abgeschnitten und als lediglich 3 ausgegeben. Wichtig zu wissen ist ebenfalls, dass selbst wenn 3,99 gestanden hätte, nur 3 rauskommt. Es schneidet beinhart ab.

Vergleichen wir das mit .into()

let a:f32 = 3.1415;
let b:u8 = a.into();

Ausgabe
image.png

Mit .into lässt sich so einen Umwandlung nicht machen. Der Trait blockiert die unsaubere Umwandlung. Wie gesagt, kann man mit as ebenfalls machen. Die Fehlerquellen sollten im Hinterstübchen bleiben.

Belassen wirs mal fürs Erste damit. Im weiteren Verlauf werden wir wahrscheinlich noch komplexere Umwandlungsformen sehen, wo aber jetzt noch etwas das Wissen dazu fehlt. (mir auch)

Zum Schluss wieder die Zusammenfassung

fn main() {
    for mut x in 0..=255{
        let convert:char = x.into();
        print!("{}.{:?}\t",x, convert);
        x+=1;
    }
    let a:u8 = 42;
    let b: f32 = a as f32;
    let c = 4.5;
    let d = c/b;
    println!("{}:{}={}",b,c,d);

    let a:u16 = 350;
    let b:u8 = a as u8;
    println!("{}",b);

    let a:f32 = 3.1415;
    let b:u8 = a as u8;
    println!("{}",b);

    let a:f32 = 3.1415;
    let b:u8 = a.into();

}

Ausgabe

image.png

vom Editor

16.png