Débuter avec Rust

Utilisation avancée de println !

println! (et son frère, [print!](https://doc.rust-lang. org/std/macro.print!.html)) fournit un mécanisme pratique pour produire et imprimer du texte contenant des données dynamiques, similaire à la famille de fonctions “printf” que l’on trouve dans de nombreux autres langages. Son premier argument est une chaîne de format, qui dicte comment les autres arguments doivent être affichés sous forme de texte. La chaîne de format peut contenir des espaces réservés (entre {}) pour spécifier qu’une substitution doit se produire :

// No substitution -- the simplest kind of format string
println!("Hello World");
// Output: Hello World

// The first {} is substituted with a textual representation of
// the first argument following the format string. The second {}
// is substituted with the second argument, and so on.
println!("{} {} {}", "Hello", true, 42);
// Output: Hello true 42

À ce stade, vous vous demandez peut-être : comment println! a-t-il su imprimer la valeur booléenne true en tant que chaîne “true” ? {} est vraiment une instruction au formateur que la valeur doit être convertie en texte en utilisant le trait Display . Ce trait est implémenté pour la plupart des types Rust primitifs (chaînes, nombres, booléens, etc.) et est destiné à la “sortie orientée utilisateur”. Par conséquent, le nombre 42 sera imprimé en décimal comme 42, et non, disons, en binaire, c’est ainsi qu’il est stocké en interne.

Comment imprimer des types, alors, qui n’implémentent pas Display, des exemples étant Slices ([i32]), des vecteurs (Vec<i32>) ou des options (Option<&str>) ? Il n’y a pas de représentation textuelle claire de ceux-ci (c’est-à-dire une que vous pourriez insérer trivialement dans une phrase). Pour faciliter l’impression de telles valeurs, Rust a également le trait Debug et le correspondant {:?} espace réservé. D’après la documentation : “Debug doit formater la sortie dans un contexte de débogage orienté programmeur.” Voyons quelques exemples :

println!("{:?}", vec!["a", "b", "c"]);
// Output: ["a", "b", "c"]

println!("{:?}", Some("fantastic"));
// Output: Some("fantastic")

println!("{:?}", "Hello");
// Output: "Hello"
// Notice the quotation marks around "Hello" that indicate
// that a string was printed.

Debug a également un mécanisme intégré de jolie impression, que vous pouvez activer en utilisant le modificateur # après les deux-points :

println!("{:#?}", vec![Some("Hello"), None, Some("World")]);
// Output: [
//    Some(
//        "Hello"
//    ),
//    None,
//    Some(
//        "World"
//    )
// ]

Les chaînes de format vous permettent d’exprimer équitablement des substitutions complexes :

// You can specify the position of arguments using numerical indexes.
println!("{1} {0}", "World", "Hello");
// Output: Hello World

// You can use named arguments with format
println!("{greeting} {who}!", greeting="Hello", who="World");
// Output: Hello World

// You can mix Debug and Display prints:
println!("{greeting} {1:?}, {0}", "and welcome", Some(42), greeting="Hello");
// Output: Hello Some(42), and welcome

println! et vos amis vous avertiront également si vous essayez de faire quelque chose qui ne fonctionne pas, plutôt que de planter à l’exécution :

// This does not compile, since we don't use the second argument.
println!("{}", "Hello World", "ignored");

// This does not compile, since we don't give the second argument.
println!("{} {}", "Hello");

// This does not compile, since Option type does not implement Display
println!("{}", Some(42));

À la base, les macros d’impression Rust sont simplement des enveloppes autour de la macro format!, qui permet de construire une chaîne par couture ensemble des représentations textuelles de différentes valeurs de données. Ainsi, pour tous les exemples ci-dessus, vous pouvez remplacer println! par format! pour stocker la chaîne formatée au lieu de l’imprimer :

let x: String = format!("{} {}", "Hello", 42);
assert_eq!(x, "Hello 42");

Sortie console sans macros

// use Write trait that contains write() function
use std::io::Write;

fn main() {
    std::io::stdout().write(b"Hello, world!\n").unwrap();
}
  • Le trait std::io::Write est conçu pour les objets qui acceptent les flux d’octets. Dans ce cas, un handle vers la sortie standard est acquis avec std::io::stdout().

  • Write::write() accepte une tranche d’octets (&[u8]), qui est créée avec un littéral de chaîne d’octets (b"<string>"). Write::write() renvoie un Result<usize, IoError>, qui contient soit le nombre d’octets écrits (en cas de succès), soit une valeur d’erreur (en cas d’échec).

  • L’appel à Result::unwrap() indique que l’appel devrait réussir (Result<usize, IoError> -> usize), et la valeur est rejetée.

Exemple minimal

Pour écrire le programme traditionnel Hello World en Rust, créez un fichier texte appelé “hello.rs” contenant le code source suivant :

fn main() {
    println!("Hello World!");
}

Cela définit une nouvelle fonction appelée main, qui ne prend aucun paramètre et ne renvoie aucune donnée. C’est là que votre programme démarre son exécution lorsqu’il est exécuté. À l’intérieur, vous avez un println!, qui est une macro qui imprime du texte dans la console.

Pour générer une application binaire, invoquez le compilateur Rust en lui passant le nom du fichier source :

$ rustc hello.rs

L’exécutable résultant aura le même nom que le module source principal, donc pour exécuter le programme sur un système Linux ou MacOS, exécutez :

$ ./hello
Hello World!

Sur un système Windows, exécutez :

C:\Rust> hello.exe
Hello World!

Commencer

Installation

Avant de pouvoir faire quoi que ce soit en utilisant le langage de programmation Rust, vous devrez l’acquérir—[soit pour Windows][1] ou en utilisant votre terminal sur des systèmes de type Unix, où $ symbolise l’entrée dans le Terminal:

$ curl https://sh.rustup.rs -sSf | sh

Cela récupérera les fichiers requis et configurera la dernière version de Rust pour vous, quel que soit le système sur lequel vous vous trouvez. Pour plus d’informations, voir [page du projet][rustup].

_Remarque : certaines distributions Linux (par exemple [Arch Linux]) fournissent rustup sous forme de package, qui peut être installé à la place. Et bien que de nombreux systèmes de type Unix fournissent rustc et cargo comme packages séparés, il est toujours recommandé d’utiliser [rustup] à la place car cela facilite beaucoup la gestion de plusieurs canaux de publication et la compilation croisée. _

[Arch Linux] : https://www.archlinux.org/packages/community/x86_64/rustup/ [rustup] : https://github.com/rust-lang-nursery/rustup.rs

Compilateur de rouille

Nous pouvons maintenant vérifier si Rust a bien été installé sur nos ordinateurs en exécutant la commande suivante soit dans notre terminal, si sous UNIX, soit à l’invite de commande, si sous Windows :

$ rustc --version

Si cette commande réussit, la version du compilateur de Rust installée sur nos ordinateurs s’affichera sous nos yeux.

Cargaison

Avec Rust vient Cargo, qui est un outil de construction utilisé pour gérer vos packages et projets Rust. Pour vous assurer que cela est également présent sur votre ordinateur, exécutez ce qui suit dans la console - la console se référant au terminal ou à l’invite de commande selon le système sur lequel vous vous trouvez :

$ cargo --version

Tout comme la commande équivalente pour le compilateur Rust, cela renverra et affichera la version actuelle de Cargo.

Pour créer votre premier projet Cargo, vous pouvez vous diriger vers [Cargo][2].

Alternativement, vous pouvez compiler des programmes directement en utilisant rustc comme indiqué dans [Exemple minimal][3].

[1] : http://win.rustup.rs/ [2] : https://www.wikiod.com/fr/rust/cargaison#Créer un nouveau projet [3] : https://www.wikiod.com/fr/rust/debuter-avec-rust#Exemple minimal