Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Rust 1.39.0 sonne l'arrivée en version stable des fonctions async
Et la possibilité de placer des attributs dans les paramètres des fonctions

Le , par Stéphane le calme

0PARTAGES

19  0 
L'équipe responsable du développement de Rust a annoncé la disponibilité de Rust 1.39.0. Voici quelques points importants.

L'.await (attente) est terminée, dites bonjour aux async fn

Dans Rust 1.36,le trait Future a été proposé en version stable. L'équipe espérait donner aux « crate » importants, aux bibliothèques et à l'écosystème le temps de se préparer à async / .await.

Il aura fallu attendre l'arrivée de Rust 1.39 pour mettre un terme à cette attente. En effet, à partir de cette version, async / .await est désormais proposé en version stable. Concrètement, cela signifie que vous pouvez désormais définir des fonctions et blocs async et les mettre en .await.

Une fonction async, que vous pouvez annoncer en écrivant async fn au lieu de fn, ne fait rien d'autre que retourner un Future lorsqu'elle est appelée. Ce Future est un calcul suspendu que vous pouvez conduire à son terme en le mettant en .await. Outre async fn figurent les blocs async { ... } et async move { ... }, qui agissent comme des fermetures et peuvent être utilisés pour définir des "littéraux asynchrones".


En somme, Async-wait est un moyen d'écrire des fonctions qui peuvent "mettre en pause", rendre le contrôle au runtime, puis reprendre à l'endroit où elles se sont arrêtées. Généralement, ces pauses doivent attendre les E / S, mais il peut y avoir un grand nombre d'utilisations. Vous connaissez peut-être l’async-wait de JavaScript ou C #. La version de Rust de la fonctionnalité est similaire, mais avec quelques différences clés.

Pour vous en servir, commencez par écrire async fn au lieu de fn
Code Rust : Sélectionner tout
async fn first_function() -> u32 { .. }

Contrairement aux fonctions régulières, appeler une async fn n'a pas d'effet immédiat. Au lieu de cela, elle retourne Future, une opération suspendue qui attend d'être exécutée. C'est l'opérateur .await qui va lancer son exécution :

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
async fn another_function() {
    // Create the future:
    let future = first_function();
 
    // Await the future, which will execute it (and suspend
    // this function if we encounter a need to wait for I/O): 
    let result: u32 = future.await;
    ...
}

Cet exemple montre la première différence entre Rust et d'autres langages : nous écrivons future.await au lieu de await future, une syntaxe qui s'imbrique mieux avec l'opérateur ? de Rust pour propager des erreurs (qui, après tout, sont très courantes dans les E / S). Vous pouvez simplement écrire future.await? pour attendre le résultat d'un futur et propager des erreurs.

Références aux liaisons dans match

Lors de la recherche de motif dans Rust, une variable, également appelée "liaison", peut être liée de la manière suivante:
  • par référence, immuablement ou mutuellement. Ceci peut être réalisé explicitement par exemple via ref my_var ou ref mut my_var respectivement. La plupart du temps cependant, le mode de liaison sera automatiquement déduit.
  • par valeur : soit par copie, lorsque le type de la variable liée implémente Copy, ou sinon par déplacement.

Auparavant, Rust interdisait de prendre des références partagées pour des liaisons par déplacement dans les expressions if ou match, ce qui signifie que le code suivant aurait été rejeté :

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn main() {
    let array: Box<[u8; 4]> = Box::new([1, 2, 3, 4]);
 
    match array {
        nums
//      ---- `nums` is bound by move.
            if nums.iter().sum::<u8>() == 10
//                 ^------ `.iter()` implicitly takes a reference to `nums`.
        => {
            drop(nums);
//          ----------- `nums` was bound by move and so we have ownership.
        }
        _ => unreachable!(),
    }
}

Avec Rust 1.39.0, l'extrait de code ci-dessus est maintenant accepté par le compilateur. L'équipe espère que cela donnera une expérience plus lisse et plus cohérente avec les expressions match en général.

Attributs sur les paramètres de fonction

Avec Rust 1.39.0, les attributs sont désormais autorisés dans les paramètres des fonctions, des fermetures et des pointeurs de fonction. Alors qu'avant, vous auriez peut-être écrit:

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
#[cfg(windows)]
fn len(slice: &[u16]) -> usize {
    slice.len()
}
#[cfg(not(windows))] 
fn len(slice: &[u8]) -> usize {
    slice.len()
}

Vous pouvez désormais écrire plus succinctement

Code Rust : Sélectionner tout
1
2
3
4
5
6
fn len(
    #[cfg(windows)] slice: &[u16], // This parameter is used on Windows.
    #[cfg(not(windows))] slice: &[u8], // Elsewhere, this one is used.
) -> usize {
    slice.len()
}

Les attributs que vous pouvez utiliser dans cette position incluent :
  1. Compilation conditionnelle: cfg et cfg_attr
  2. Les contrôles allow, warn, deny, et forbid
  3. LEs attributs auxiliaires utilisés par les attributs de macro procéduraux appliqués aux éléments.

Source : Rust

Une erreur dans cette actualité ? Signalez-le nous !