Syntaxe de base de Rust

Les variables, les types de base, les fonctions, les commentaires et le flux de contrôle sont des concepts de programmation présents dans presque tous les langages de programmation.

Ces concepts fondamentaux seront présents dans chaque programme Rust. Les apprendre tôt vous permettra d'apprendre à utiliser Rust aussi rapidement que possible.

Variables

Tout d'abord, il faut noter que Rust est un langage à typage fort, mais il a la capacité de déduire automatiquement le type des variables. Cela peut facilement être confondu avec des langages à typage faible.

Par défaut, les variables en Rust sont immuables, sauf si elles sont déclarées comme mutables à l'aide du mot-clé `mut`.

let a = 123;       // 不可变变量
let mut b = 10;  // 可变变量

Pour déclarer une variable, vous devez utiliser leletmot-clé. Par exemple :

let a = 123;

Les développeurs qui n'ont appris que JavaScript sont très sensibles à cette affirmation, tandis que les développeurs qui n'ont appris que C ont du mal à la comprendre.

Après cette déclaration, les trois lignes de code suivantes sont toutes interdites :

a = "abc";
a = 4.56; 
a = 456;

L'erreur de la première ligne est qu'après avoir déclaré `a` comme 123, `a` est déterminé comme étant un entier, et vous ne pouvez pas lui affecter une valeur de chaîne.

L'erreur de la deuxième ligne est qu'une conversion automatique entraînerait une perte de précision numérique, et Rust n'autorise pas les conversions de type automatiques qui perdent de la précision.

L'erreur de la troisième ligne est que `a` n'est pas une variable mutable.

Les deux premières erreurs sont faciles à comprendre, mais que signifie la troisième ? `a` n'est-il pas une variable ?

Cela est lié à la conception de Rust pour la sécurité en haute concurrence : au niveau du langage, il essaie de minimiser les situations où les valeurs des variables peuvent être modifiées. Ainsi, la valeur de `a` est immuable. Mais cela ne signifie pas que `a` n'est pas une « variable » (le mot anglais `variable`) ; la documentation officielle appelle les variables comme `a` des « variables immuables ».

Si une partie de notre programme s'exécute en supposant qu'une valeur ne changera jamais, tandis qu'une autre partie de notre code modifie cette valeur, alors la première partie peut ne pas se comporter comme prévu. Les erreurs causées par cela sont difficiles à trouver par la suite. C'est la raison pour laquelle Rust a conçu ce mécanisme.

Bien sûr, rendre une variable « mutable » ne nécessite que lemutmot-clé.

let mut a = 123;
a = 456;

Ce programme est correct.

Différence entre les constantes et les variables immuables

Puisque les variables immuables sont immuables, ne sont-elles pas simplement des constantes ? Pourquoi sont-elles appelées variables ?

Il existe toujours une différence entre les variables et les constantes. En Rust, le programme suivant est valide :

let a = 123;   // 可以编译,但可能有警告,因为该变量没有被使用
let a = 456;

Mais si `a` est une constante, c'est invalide :

const a: i32 = 123;
let a = 456;

La valeur d'une variable peut être « reliée à nouveau », mais elle ne peut pas être modifiée d'elle-même avant d'être « reliée à nouveau ». Cela garantit que, dans chaque région après une « liaison », le compilateur peut raisonner pleinement sur la logique du programme. Bien que Rust dispose d'une inférence de type automatique, dans certains cas, déclarer le type est plus pratique :

let a: u64 = 123;

Ici, `a` est déclaré comme une variable entière non signée de 64 bits. Si le type n'était pas déclaré, `a` serait automatiquement inféré comme une variable entière signée de 32 bits, ce qui a un impact significatif sur la plage de valeurs que `a` peut contenir.

Types de données

Rust est un langage à typage statique. Vous pouvez spécifier explicitement les types lors de la déclaration de variables, mais vous pouvez généralement vous fier à l'inférence de type.

Types de base :i32 (entier signé 32 bits), u32 (entier non signé 32 bits), f64 (nombre à virgule flottante 64 bits), bool (booléen), char (caractère)

Exemple

let x: i32 = 42;
let y: f64 = 3.14;
let is_true: bool = true;
let letter: char = 'A';

Fonctions

Les fonctions Rust sont définies à l'aide du mot-cléfn, et le type de retour est spécifié à l'aide du symbole flèche->.

Exemple

fn add(a: i32, b: i32) -> i32 {
    a + b
}

Si une fonction n'a pas de valeur de retour, le type par défaut est()(c'est-à-dire le tuple vide).

Flux de contrôle

expression `if`

Exemple

let number = 7;
if number < 5 {
    println!("inférieur à 5");
} else {
    println!("supérieur ou égal à 5");
}

boucle `loop` :`loop` est une boucle infinie en Rust ; vous pouvez utiliser `break` pour sortir de la boucle.

Exemple

let mut counter = 0;
loop {
    counter += 1;
    if counter == 10 {
        break;
    }
}

boucle `while`

Exemple

let mut number = 3;
while number != 0 {
    println!("{}!", number);
    nombre -= 1;
}

boucle `for`

Exemple

for number in 1..4 {
    println!("{}!", number);
}

Propriété

La propriété en Rust est un mécanisme unique de gestion de la mémoire. Ses concepts clés incluent la propriété, l'emprunt et les références.

Règles de propriété :

  • Chaque valeur en Rust a un seul propriétaire.
  • Chaque valeur ne peut avoir qu'un seul propriétaire à un instant donné.
  • Lorsque le propriétaire sort de la portée, la valeur sera libérée.
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权被转移给了 s2
// println!("{}", s1); // 此处编译会报错,因为 s1 已不再拥有该值

Emprunt et références :L'emprunt vous permet de référencer des données sans en prendre possession, mis en œuvre via le&symbole.

fn main() {
    let s = String::from("hello");
    let len = calculate_length(&s);  // 借用
    println!("The length of '{}' is {}.", s, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Structures

Les structures sont utilisées pour créer des types personnalisés, et leurs champs peuvent contenir plusieurs types de données.

Exemple

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

let user1 = User {
    username: String::from("someusername"),
    email: String::from("[email protected]"),
    sign_in_count: 1,
    active: true,
};

Énumérations

Les énumérations vous permettent de définir un type de données parmi plusieurs possibles.

Exemple

enum IpAddrKind {
    V4,
    V6,
}

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

Filtrage par motif (match)

`match` est un puissant outil de contrôle de flux en Rust, semblable à une instruction `switch`.

Exemple

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

Gestion des erreurs

Rust dispose de deux façons principales de gérer les erreurs :Result<T, E>etOption<T>。

Résultat :

Exemple

enum Result<T, E> {
    OK(T),
    Err(E),
}

fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("Division par zéro"))
    } else {
        OK(a / b)
    }
}

Option :

Exemple

fn get_element(index: usize, vec: &Vec<i32>) -> Option<i32> {
    if index < vec.len() {
        Some(vec[index])
    } else {
        Aucune
    }
}

Durées de vie de la propriété et de l'emprunt

Rust utilise les durées de vie pour garantir que les références sont valides. Les annotations de durée de vie sont notées par'aetc., mais dans les cas courants, le compilateur les inférera automatiquement.

Exemple

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Masquage

Le concept de masquage est différent de « override » ou « overload » dans d'autres langages orientés objet. Le masquage est ce qui était appelé « rebinding » précédemment ; les guillemets ont été utilisés pour désigner le concept avant son introduction.

Le masquage désigne le mécanisme par lequel le nom d'une variable peut être réutilisé :

Exemple

fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    println!("La valeur de x est : {}", x);
}

La sortie de ce programme est :

The value of x is: 12

Le masquage n'est pas le même concept que l'affectation à une variable mutable. Le masquage signifie utiliser le même nom pour représenter une autre entité de variable, et son type, sa mutabilité et sa valeur peuvent tous changer. Cependant, l'affectation à une variable mutable ne peut changer que sa valeur.

let mut s = "123";
s = s.len();

Ce programme provoquera une erreur : vous ne pouvez pas affecter une valeur entière à une variable de chaîne de caractères.

Autres extensions