<
Media
>
Article

Rust : ce langage natif safe et puissant

7 min
18
/
03
/
2020

En 2020, quand on parle de langage "natif" ou bas niveau, étonnamment, on pense encore beaucoup au C et au C++. Bien que les dernières versions du C++ fassent évoluer la syntaxe, le fond même du langage n'a pas vraiment changé.

Et il faut bien avouer qu'en face de langages plus haut niveau comme le JavaScript ou le Python et l'évolution fulgurante de tous les frameworks de la communauté web, le C++ souffre de quelques défauts qui deviennent récurrents, notamment :

  • Intégrer une bibliothèque peut être vraiment (très) fastidieux, même parfois jusqu'au point de préférer réimplémenter la fonctionnalité soi-même.
  • Il y a souvent des problèmes d'accès mémoire : des pointeurs zombies, des erreurs de segmentation, des conflits d'accès à des ressources partagées entre plusieurs threads...

Rust, lui, ne souffre pas de ces défauts.

Symbol Rust

La philosophie Rust

Rust est un langage safe grâce à un système de borrow checker redoutable :

  • Les variables sont par défaut immutables.
  • Chaque variable mutable ne peut être modifiée que dans un seul scope à la fois, c'est le concept d'ownership.
  • La durée de vie est vérifiée pour chaque variable : le lifetime. Si le compilateur a un doute par exemple lorsqu'on compare 2 variables entre elles, il faudra spécifier de manière explicite la durée de vie de chaque variable.

Le compilateur <span class="css-span">rustc</span> est strict. Vraiment strict. Dites vous bien que vous ne vous êtes jamais vraiment battu avec un compilateur tant que vous n'avez pas essayé <span class="css-span">rustc</span> ! Mais la bonne nouvelle, c'est que ses messages d'erreurs sont explicites, et les suggestions aideront à résoudre les problèmes.

Rust a donc une syntaxe qui se veut explicite mais concise.

Avec Cargo : un super environnement de dev

Packages

Rust et son gestionnaire de paquets Cargo fonctionnent sous forme de modules hiérarchiques. Un programme Rust est donc structuré, et l'intégration d'une bibliothèque externe consiste simplement à ajouter <span class="css-span">nom_module=1.0.0</span> dans le <span class="css-span">Cargo.toml</span> et à laisser la commande <span class="css-span">cargo install</span> faire le reste ! (Hey les développeurs Node.js, ça vous rappelle quelque chose ?)

Tests

Avec <span class="css-span">cargo test</span> il est possible d'exécuter toutes les portions de code taggées <span class="css-span">#[test]</span> pour les tests unitaires :

```rust

   -- CODE language-rust--

#[test]
fn test_add() {
   assert_eq!(add(1, 2), 3);
}

```

mais aussi tous les fichiers placés dans un répertoire <span class="css-span">test/</span> pour les tests d'intégration.

Compilation

Le code se compile avec <span class="css-span">cargo build</span> ou directement <span class="css-span">cargo run</span> pour les feignants ;)

Il est possible de faire de la cross-compilation en spécifiant la target (et en installant le nécessaire) : <span class="css-span">cargo build --target=arm-linux-androideabi</span>

Il est même possible de compiler en Web Assembly pour intégrer un traitement important côté client, comme expliqué dans ce tutoriel de Mozilla.

Autres concepts clés du langage

Par ailleurs, le Rust est également doté (liste non exhaustive bien sûr):

  • d'inférence de type : <span class="css-span">let a = 1 + 2; // -> i32</span>
  • de fonction lambda appelées closures :

```rust

   -- CODE language-rust--

let closure_annotated = |i: i32| -> i32 { i + 1 };<code><pre>

  • de tuples : <span class="css-span">let tuple = (1, "hello", 4.5, true);</span>
  • de structures :

<pre><code>let user1 = User {
   email: String::from("someone@example.com"),
   username: String::from("someusername123"),
   active: true,
   sign_in_count: 1,
};

```

Mais également d'objets bien spécifiques au langage :

  • les objets <span class="css-span">Option et Result</span> qui servent à encapsuler de manière sûre le résultat d'une fonction
  • les traits : on peut les comparer au design pattern "Interface". Ils sont l'unique solution pour l'héritage de fonctions sur des structures de données. L'avantage en Rust, c'est que beaucoup de traits standards sont déjà implémentés, et il suffit alors de les spécifier sur une structure pour bénéficier de tous leurs bienfaits : <span class="css-span">Debug, Format, Serialize, Clone, Copy,...</span>
  • <span class="css-span">match</span> : les débutants croiront qu'il s'agit d'un simple <span class="css-span">switch/case</span>. Erreur ! C'est bien plus que ça ! Un <span class="css-span">match</span> ne se contente pas de tester des valeurs, mais des patterns !

let x = 'c';

match x {    'a'..='i' => println!("early ASCII letter"), // with range pattern
   'j' => println("middle ASCII letter"),
   'k'..='z' => println!("late ASCII letter"),
   _ => println!("something else"), // all other values
}

À noter aussi que le compilateur fera la tête tant que toutes les valeurs possibles de <span class="css-span">x</span> ne seront pas gérées par le <span class="css-span">match</span> ! Souvenez-vous, Rust est un langage safe !

  • macros (pour un public averti) : contrairement au C++, une macro n'est pas seulement du code qui se substituera à un symbole : c'est une instruction de pré-compilation qui va réagir à des patterns, tel un parseur de code ! On les reconnaît facilement, car elles se terminent par un point d'exclamation, comme <span class="css-span">println!(...)</span>. Voici par exemple la définition de la macro standard <span class="css-span">vec![...]</span> :

```rust

   -- CODE language-rust--

macro_rules! vec {
   ( $( $x:expr ),* ) => {
       {
           let mut temp_vec = Vec::new();
           $(
                temp_vec.push($x);
           )*
           temp_vec
       }
   };
}

```

Elle est très pratique pour instancier rapidement un conteneur vec directement avec des valeurs :

let my_vec = vec![1, 2, 3, 10];

... et bien d'autres !

Pour aller plus loin

La doc officielle pour apprendre le Rust : Rust by Example

Essayer du Rust en ligne, sans rien installer : Rust Playground

No items found.
ça t’a plu ?
Partage ce contenu
Jean-Noël

Jean-Noël aime sa guitare, sa PS4 (quoi de mieux que de réaliser un super combo sur sa manette) et coder... mais de préférence en Typescript !

Et oui, le Typescript, c’est son dada ! Il y a une très forte interopérabilité, le typage apporte de la rigueur au JS, et tout fonctionne très bien, très vite ! En revanche, quand il s’agit d’algorithmes, il préfère le Rust ! C’est le seul langage pour lequel, lorsqu’il a réussi à compiler, il peut respirer en criant : « MON CODE EST SUUUUR !!! ».

On ne sait pas si c’est pour pouvoir rédiger des tas d’articles pour le blog YOUNUP mais il nous a confié rêver de pouvoir regénérer ses cellules pour une jeunesse et un savoir sans limite. Un mix entre le film « Bienvenue à Gattaca » et les écrits de « Laurent Alexandre » ?