Mozilla annonce la disponibilité de Rust 1.16
Qui s'accompagne de la sous-commande cargo check

Le , par Stéphane le calme, Chroniqueur Actualités
L’équipe responsable du développement de Rust a annoncé la disponibilité de la version stable 1.16. L’un des ajouts majeurs apportés au langage de programmation est la sous-commande cargo check laquelle, selon l’équipe, devrait vous aider à accélérer votre flux de travail dans bien des cas.

Que fait-elle exactement ? Avant d’y parvenir, il faut d’abord s’intéresser à la façon dont rustc compile votre code. Il existe de nombreuses étapes distinctes par lesquelles le compilateur passe entre votre code source et la production du binaire final. Pour observer ces étapes, et surtout combien de temps et de mémoire elles prennent, vous pouvez lancer la commande -Z time-passes à un compilateur nightly.

rustc .\hello.rs -Z time-passes
time: 0.003; rss: 16MB parsing
time: 0.000; rss: 16MB recursion limit
time: 0.000; rss: 16MB crate injection
time: 0.000; rss: 16MB plugin loading
time: 0.000; rss: 16MB plugin registration
time: 0.049; rss: 34MB expansion
<snip>

Comme vous pouvez le constater avec cet exemple, il y a plusieurs étapes. Cependant, nous pouvons les regrouper en deux grandes catégories :
  • tout d'abord, rustc effectue toutes ses vérifications de sécurité, il s'assure que votre syntaxe est correcte, etc. ;
  • ensuite, une fois qu'il a terminé ses routines de vérification, il produit le code binaire réel que vous finissez par exécuter.

Il s’avère que cette seconde grande étape prend beaucoup de temps qui n'est pas souvent nécessaire. Autrement dit, lorsque vous travaillez sur un code Rust, de nombreux développeurs vont procéder comme suit :
  1. Écrire une portion de code ;
  2. Exécuter cargo build pour s'assurer qu'il n’y a pas d’erreurs de compilation ;
  3. Répéter les étapes 1 et 2 si nécessaire ;
  4. Exécutez cargo test pour s'assurer qu’il n’y pas d’erreurs dans les tests ;
  5. Retour à l’étape numéro 1.

En réalité, une fois rendu à l’étape 2, il n’est pas vraiment question de lancer l’exécution de votre code : il s’agit d’avoir un feedback du compilateur, mais pas dans l’optique d’exécuter le binaire. C’est dans ce cas d’utilisation que cargo check intervient : il exécute toutes les vérifications du compilateur, mais ne produit pas le binaire final.

Alors concrètement de quel pourcentage de vitesse les développeurs vont-ils bénéficier ? Les ingénieurs indiquent que, comme c'est le cas avec les questions de performance, la réponse est « ça dépend ». Toutefois, ils ont fourni un benchmark permettant de comparer des gains de vitesse sur différentes catégories.

Fonctionnalités de cargo

En plus de cargo check, Cargo et crates.io ont été retravaillés. Par exemple, cargo build et cargo docsupportent désormais le flag --all pour construire et documenter tous les “crate” dans votre espace de travail en une commande.

Pour rappel, Rust a deux termes distincts qui se rapportent au système de module : 'crate' et 'module'. Un crate est synonyme d'une « bibliothèque » ou d'un « paquet » dans d'autres langages. Par conséquent, "Cargo”, en tant que nom de l'outil de gestion de paquets de Rust, permet de diffuser les “crate” à d’autres avec Cargo. Les “crate” peuvent produire un exécutable ou une bibliothèque, selon le projet.

Autres améliorations

Afin de supporter cargo check, rustc fournit désormais un nouveau type de fichier : .rmeta. Ce fichier contient uniquement des métadonnées sur un “crate” en particulier. cargo check en a besoin pour vos dépendances afin de laisser le compilateur vérifier par exemple les types.

Source : blog Rust


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse

Avatar de joublie joublie - Membre actif https://www.developpez.com
le 18/03/2017 à 13:41
[B]cargo check[/C]

" Alors concrètement de quel pourcentage de vitesse les développeurs vont-ils bénéficier ? " C'est assez mal rédigé, non ?
Avatar de Uther Uther - Expert éminent https://www.developpez.com
le 18/03/2017 à 22:21
Oui, c'est un traduction assez moyenne de l'article.

Niveau vitesse ça dépend du type de code, certains type de code sont plus couteux que d'autres a compiler. Sur mes programmes, la différence par rapport entre une vérification seule et une compilation (sans optimisation) est de l'ordre de 3 à 6 fois plus rapide.

Après "make check" ne sert que a vérifier s'il y a des erreur de compilation. Si on veut tester, il faudra quand même faire une construction complète après.
Avatar de Songbird_ Songbird_ - Rédacteur/Modérateur https://www.developpez.com
le 28/04/2017 à 21:22
Rust 1.17 est désormais disponible en version stable,
et apporte, avec elle, de nombreuses améliorations

Ce 27 avril, l'équipe Rust a annoncé la sortie de la version 1.17 de Rust avec son lot de (bonnes !) surprises.
Avant de vous pencher sur les fonctionnalités de cette toute dernière version stable, n'oubliez pas que rustup vous permet d'installer cette dernière simplement (si vous ne disposez pas de rustup sur votre poste, n'hésitez pas à le télécharger).

Code bash : Sélectionner tout
rustup update stable

Quoi de neuf dans la 1.17.0  ?

Cette version est principalement axée sur la souplesse de la syntaxe, les raccourcis et l'intelligibilité des erreurs.

Lifetime des constantes

Avant la 1.17.0, les références constantes devaient être annotées manuellement de la durée de vie 'static, sans quoi le compilateur risquait de vous renvoyer une erreur.

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
struct Foo;
const BAR: &'static Foo = &Foo;
 
// ou pour reprendre les exemples du billet
 
const NAME: &'static str = "Ferris";
static NAME: &'static str = "Ferris";
 
// L'annotation commence à devenir relativement lourde
const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"];


Pour remédier à cela, la nouvelle version propose de ne plus préciser cette durée de vie dans le type, mais de laisser le compilateur le faire à notre place (puisque, quoi qu'il arrive, une constante devrait avoir une durée de vie équivalente à celle de l'exécution du programme), allégeant drastiquement les annotations.

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
struct Foo;
const BAR: &Foo = &Foo;
 
// ou pour reprendre les exemples du billet
 
const NAME: &str = "Ferris";
static NAME: &str = "Ferris";
 
// L'annotation commence à devenir relativement lourde
const NAMES: &[&str; 2] = &["Ferris", "Bors"];


Code MIR de la constante BAR:

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
const BAR: &'static Foo = { // le compilateur ajoute bien la lifetime
    let mut _0: &'static Foo;            // return pointer
    let mut _1: &'static Foo;
    let mut _2: Foo;
 
    bb0: {
        _2 = Foo::{{constructor}};       // scope 0 at <anon>:2:20: 2:23
        _1 = &_2;                        // scope 0 at <anon>:2:19: 2:23
        _0 = &(*_1);                     // scope 0 at <anon>:2:19: 2:23
        return;                          // scope 0 at <anon>:2:1: 2:24
    }
}


Assignation des champs raccourcie

Précédemment, les assignations effectuées sur les champs d'un objet lors de sa construction se faisaient de cette manière :

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Foo{
	x: f64,
	y: f64,
	z: f64,
}
 
fn main() -> (){
    let x = 10f64;
    let y = 15f64;
    let z = 20f64;
	let bar = Foo{
        x: x,
        y: y,
        z: z,
    };
}


Vous pouvez désormais omettre x:, y: et z:.

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
struct Foo {
    x: f64,
    y: f64,
    z: f64,
}
fn main() {
    let bar = Foo { x, y, z };
    // l'ordre importe peu, exemple:
 
    let bar = Foo { z, x, y };
    println!("x:{0},y:{1},z:{2}", bar.x, bar.y, bar.z);
    // affiche: x:10,y:15,z:20
}


Dans le billet, l'équipe Rust explique que ce raccourci est inspiré de celui proposé par l'ECMAScript 6.

L'opérateur +

En tant que débutant, il pourrait être aisé de croire qu'une concaténation entre deux primitifs &str s'effectue avec l'opérateur +, ce qui n'est bien entendu pas le cas. Pour épauler ces nouveaux utilisateurs, le message d'erreur a été réécrit.

(Exemple tiré du billet)
Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// code
"foo" + "bar"
 
// Ancien message d'erreur
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
note: an implementation of `std::ops::Add` might be missing for `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
 
// Nouveau message d'erreur
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
  = note: `+` can't be used to concatenate two `&str` strings
help: to_owned() can be used to create an owned `String` from a string
reference. String concatenation appends the string on the right to the string on
the left and may require reallocation. This requires ownership of the string on
the left.
  |     "foo".to_owned() + "bar"


À propos de Cargo

Comme vous le savez, Cargo est le système de build natif du langage Rust. Pour cette version, il a également subi quelques modifications.

Jusqu'ici, lorsque nous avions besoin de personnaliser le processus de compilation (pour compiler des sources non-Rust, par exemple), il était nécessaire de renseigner l'option build suivie du chemin du fichier chargé d'aller chercher les ressources désirées. Toutefois, une grande majorité des utilisateurs de cargo se contentent de créer le fichier build.rs à la racine du projet, ce qui rend (dans ce cas) l'option inutile. En réponse à cela, désormais, si aucun chemin n'est renseigné dans le manifest Cargo.toml, Cargo ira chercher le fichier à la racine du projet.

Note : vous pouvez toutefois annuler cette convention, si vous le souhaitez, en assignant build = false.

Deux autres flags ont également été ajoutés aux commandes check et run. Respectivement, l'une supporte le flag --all (i.e. qui permet de vérifier la syntaxe des sources, sans les compiler, de tous les packages se trouvant dans votre espace de travail), l'autre supporte le flag --package <arg1, arg2, argn> (i.e. qui permet d'empaqueter le binaire du (ou des) package que vous lui renseignerez).

Enfin, un nouveau paquet est disponible sur crates.io pour la rédaction de la documentation de vos projets : mdbook !
C'est, en quelque sorte, un équivalent à gitbook qui vous permet de générer un site en markdown en vous proposant divers outils tels que la commande test (qui vous permet de repérer les liens morts, les fichiers inutilisés), un gestionnaire de thèmes ou encore l'expression {{#playpen your_file.rs}} qui vous permet d'intégrer du code source (qui sera compilé par le playpen) à exécuter par l'utilisateur, dans votre documentation.

À propos de rustup

Dernière nouvelle, mais pas des moindres : rustup télécharge pour vous l'intégralité de la documentation officielle de Rust sur votre poste lorsque vous installez une nouvelle version du langage. Celui-ci embarquera le livre officiel de la version stable, le Rustonomicon et la documentation des versions encore instables du langage.

Pour y accéder depuis votre terminal, il vous suffit de taper rustup doc.

En vous souhaitant une bonne lecture !

Notez toutefois que d'autres fonctionnalités ont été ajoutées dans cette version, n'hésitez pas à vous rendre sur le billet relatif à l'annonce.

Source : Rust Core Team blog

Et vous ?

Quelle(s) fonctionnalité(s) souhaiteriez-vous voir apparaître dans les prochaines versions  ?

Voir aussi

Mozilla annonce la disponibilité de Rust 1.16, qui s'accompagne de la sous-commande cargo check

Rust 1.13.0 est disponible, avec des optimisations du compilateur et un nouvel opérateur « ? » pour mieux gérer les exceptions

FAQ sur la programmation en langage Rust
Avatar de Songbird_ Songbird_ - Rédacteur/Modérateur https://www.developpez.com
le 10/06/2017 à 4:10
Rust 1.18 est disponible en version stable
et apporte une optimisation sur l'alignement mémoire

EDIT: 13/06/2017
Une issue sur le dépôt de Cargo a été ouverte, et les nouveaux flags annoncés pour ce dernier dans le billet de la version 1.18 étaient en fait prévus pour la 1.19. Ne soyez donc pas étonnés si vous ne parvenez pas à les utiliser dans votre version actuelle.
Quoi de neuf dans la 1.18 ?

Cette version est un agrégat de fonctionnalités venant fignoler ce qui avait été ajouté dans les versions précédentes, comme nous allons le voir plus bas, et ce n'est pas pour nous déplaire !

Réécriture du livre officiel

Commençons par les ressources gravitant autour du langage.

L'équipe Rust a annoncé la réécriture du livre officiel "The Rust Programming Language" jugeant, après ces deux dernières, que de nouvelles explications devaient être apportées à propos des concepts abordés dans le livre.
Vous êtes, bien entendu, invité à consulter la seconde édition sur le site de la documentation officielle, mais gardez tout de même à l'esprit que vous lisez une ébauche et que de nouveaux chapitres seront apportés dans la version 1.19 de Rust.

Notez aussi qu'une version papier sera proposée, lors de la publication finale du livre.

Extension du mot-clé pub

Comme nous le savons, toutes les ressources d'un module rust sont, par défaut, privées et le mot-clé pub permet de remédier à cela.
Avec la 1.18, pub gagne en précision:

Code Rust : Sélectionner tout
pub(crate) bar;


Il est désormais possible grâce aux () de définir le contexte dans lequel une ressource (e.g. structures, énumérations, fonctions) peut être visible. En l'occurrence, lorsque vous utilisez le mot-clé crate, vous établissez la restriction suivante: bar est visible pour tous les composants du package, mais pas en-dehors.
Ces restrictions peuvent vous faciliter la tâche, si vous souhaitez user d'une API qui ne devrait communiquer qu'avec les composants de votre package.

Vous pouvez également spécifier un chemin comme ceci:

Code Rust : Sélectionner tout
pub(in a::b::c) foo;

Vous rendez donc visible cette ressource dans la hiérarchie a::b::c, mais nulle part ailleurs.

a, b et c doivent être, en revanche, des modules parents de foo.

Pour plus d'informations à propos de cette fonctionnalité, je vous invite à consulter sa RFC et la documentation officielle.

Support du flag /SUBSYSTEM

Pour les utilisateurs Windows, la 1.18 apporte l'attribut #![windows_subsystem]. Voici un exemple d'utilisation :

Code Rust : Sélectionner tout
1
2
3
 
#![windows_subsystem(console)]
#![windows_subsystem(windows)]


Ces arguments vous permettent de contrôler le flag /SUBSYSTEM et de choisir l'environnement dans lequel sera exécuté votre programme. Ils peuvent donc être utiles, par exemple, lorsque vous développez une application supportant une interface graphique et que vous ne souhaitez plus voir la console clignoter au lancement de votre programme. Vous utiliserez donc windows pour régler ce problème.
Pour le moment, seuls les environnements console et windows sont supportés par Rust.


Rustc

Optimisation de l'alignement mémoire

Il est possible d'aligner des données pour réduire le temps des accès (i.e. lecture/écriture) sur ces dernières. Toutefois, lorsqu'elles ne le sont pas (alignées), le compilateur tentera de le faire à notre place, au prix d'une consommation de mémoire plus importante.

Code Rust : Sélectionner tout
struct Suboptimal(u8, u16, u8);

Dans les versions précédentes de Rust, sur une plateforme x86_64, cette structure consommait six octets. Pourtant, en visionnant le code source, vous n'en comptez que quatre.
Les deux autres octets viennent de la compensation effectuée par le compilateur; sachant que nous avons un entier u16 ici, il devrait être aligné sur une adresse paire.
On « décale » alors le premier entier u8 d'un octet, et, pour aligner correctement la structure, on fait de même pour le dernier u8. Ce qui nous donne: 1 + 1 (compensation) + 2 + 1 + 1 (compensation) = 6 octets.

Quid de cette structure, dans ce cas ?

Code Rust : Sélectionner tout
struct Optimal(u8, u8, u16);


Celle-ci est correctement alignée, l'entier u16 se trouve sur une adresse paire, l'intégralité de la structure est alignée, aucune compensation n'est requise. Ce qui nous donne : 1 + 1 + 2 = 4 octets.

Avec la 1.18, le compilateur est capable d'aligner (si possible) une structure sans compensation (i.e. d'appliquer la signature de Optimal à SubOptimal, en quelque sorte), épargnant la mémoire par la même occasion.

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
 
// compilé avec rustc 1.18
use std::mem;
 
struct Optimal(u8, u8, u16);
struct Suboptimal(u8, u16, u8);
 
fn main() -> (){
    println!("size of Optimal:{}bytes", mem::size_of::<Optimal>());
    println!("size of Suboptimal:{}bytes", mem::size_of::<Suboptimal>());
}
Résultat:

Code : Sélectionner tout
1
2
3
size of Optimal:4bytes
size of Suboptimal:4bytes
Note: Il est possible de désactiver cette fonctionnalité avec l'annotation #[repr(C)], si vous travaillez avec des composants écrits en C.

Vous n'êtes pas très familier avec cette optimisation ? Vous trouverez des liens en bas de l'article, si vous souhaitez vous documenter.

Nouveau flag pour l'argument `--emit`

Pour examiner la MIR (Mid-level Intermediate Representation) d'un morceau de code, il était nécessaire, jusqu'ici, de consulter le compilateur en ligne. Ce n'est plus le cas !
Une fois votre compilateur mis à jour, il vous suffit de vous rendre dans le répertoire de votre choix et compiler le fichier désiré :

Code Rust : Sélectionner tout
rustc hello.rs --emit mir


Vous trouverez un fichier nommé hello.mir dans le répertoire courant, contenant la MIR :

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
fn main() -> () {
    let mut _0: ();                      // return pointer
    scope 1 {
        let _1: &str;                    // "foo" in scope 1 at hello.rs:3:6: 3:9
    }
 
    bb0: {
        StorageLive(_1);                 // scope 0 at hello.rs:3:6: 3:9
        _1 = const "Hello, there!";      // scope 0 at hello.rs:3:12: 3:27
        _0 = ();                         // scope 1 at hello.rs:2:10: 4:2
        StorageDead(_1);                 // scope 0 at hello.rs:4:2: 4:2
        return;                          // scope 0 at hello.rs:4:2: 4:2
    }
}

Cargo

Pijul

Le système de contrôle de version Pijul est désormais supporté par cargo !
Pour pouvoir créer un projet avec ce VCS, il vous suffit de taper la commande cargo new myAwesomeProject --vcs=pijul.

Pour plus d'informations, rendez-vous sur la pull request #3842.

Nouveaux flags

Le flag --all permet de compiler tous types de sources pouvant se trouver dans votre projet (i.e. exemples, sources du programme, tests, benchmarks). Vous pouvez maintenant cibler uniquement le type de sources que vous souhaitez compiler grâce aux quatre flags fraîchement débarqués :

  1. --bins: Compile toutes les sources;
  2. --examples: Compile tous les exemples;
  3. --tests: Compile tous les tests;
  4. --benches: Compile tous les benchmarks du projet.


Pour utiliser ces nouvelles fonctionnalités, il vous faudra mettre à jour cargo à la version 0.21.0.

Haiku et Android

Enfin, Cargo supporte Haiku et Android dans sa chaîne de build !

Le principal est ici, mais n'hésitez pas à consulter le billet de blog officiel si vous souhaitez vous rendre sur la release note ou encore les RFC de la version.

Source

Le blog du langage Rust
Fonctionnement de l'annotation #[repr(C)]

Ressources sur l'alignement mémoire

Vous n'êtes pas obligé de visiter tous les liens proposés pour comprendre ce qui a été rédigé. Chaque lien aborde simplement, d'une manière différente, ce concept.

Définition de l'alignement mémoire (en français)
Fonctionnement de l'alignement mémoire (en anglais)
Article d'IBM sur la manière dont le processeur gère la mémoire (en anglais)
Alignement mémoire avec C (en anglais)
Avatar de mh-cbon mh-cbon - Membre actif https://www.developpez.com
le 10/06/2017 à 12:08
Rust c'est tout de même plusieurs choses, amha.

Un langage pour répondre aux problèmes de ces prédécesseurs.
Un toolset autour du langage pour vivre avec.
Un esprit définitivement progressiste et tourné vers l'avenir.

De cet ensemble, je suis très satisfait,
c'est un changement appréciable car il est plus proche des utilisateurs,
en comparaison, pendant longtemps les avancées que l'on pouvait lire à propos des langages
concernaient des questions très théorique de la théorie des langages (preuves formelles etc)
qui finalement aboutissaient à peu de changement concret/applicable pour l'utilisateur final lambda.

J'apprécie beaucoup cela, pour autant est ce que j'aime ce langage,
bein pas trop en fait,
comme tout le monde, j'aime bien sa théorie et sa mise en pratique,
mmmmmeeeeehhhhhh
la syntaxe est bien trop complexe pour mon goût personnel.

Je ne doutes pas que je finirais par en faire,
mais aujourd'hui à cet instant, la chose n'est pas évidente pour moi
et je préfère encore me tourner vers d'autres langages
partageant certains points commun avec celui ci.
Avatar de imperio imperio - Membre chevronné https://www.developpez.com
le 10/06/2017 à 13:56
la syntaxe est bien trop complexe pour mon goût personnel.
Ah ? Voilà qui est intéressant ! Venant des langages C/C++, j'ai trouvé la syntaxe de rust nettement plus simple. De quel(s) langage(s) viens-tu du coup ?
Avatar de Songbird_ Songbird_ - Rédacteur/Modérateur https://www.developpez.com
le 10/06/2017 à 18:41

Je ne doutes pas que je finirais par en faire,
mais aujourd'hui à cet instant, la chose n'est pas évidente pour moi
et je préfère encore me tourner vers d'autres langages
partageant certains points commun avec celui ci.
Qu'est-ce qui te paraît peu évident ? Tes questions et remarques sont les bienvenues.

Concernant la syntaxe, c'est précisément ce qui me donne envie d'étudier Rust (si l'on ne parle que d'elle), car la syntaxe me semble moins... éparpillée que le C++. Cela reste très personnel, bien entendu.
D'ailleurs, si quelque chose te rebute dans la syntaxe, des ressources existent pour expliquer littéralement ce que signifie telle ou telle expression.

Très bonne journée !
Avatar de mh-cbon mh-cbon - Membre actif https://www.developpez.com
le 11/06/2017 à 10:31
D'une manière générale, même si le C est la référence pour les performances,
pour TOUT les autres domaines c'est le pire des environnements, de ce que j'en connais.
Je ne crois pas qu'il est très utile de continuer de comparer les nouveaux langages
avec ces dinosaures qui ont souffert d'avoir été les premiers sur leurs terrain de jeux.

Par exemple comparer C / Go pour moi,
selon les sujets comparés,
cela peut revenir à comparer une vieilles carriole à cheval avec la dernière F40.

Du coup la F40 gagne tout le temps, les améliorations possible ne sont plus considérés
et c'est dommage.

Citation Envoyé par imperio Voir le message
Ah ? Voilà qui est intéressant ! Venant des langages C/C++, j'ai trouvé la syntaxe de rust nettement plus simple. De quel(s) langage(s) viens-tu du coup ?
Ah oui, j'ai moi aussi déjà décrit cela autre part.

J'ai un parcours top-bottom, en gros, perl->php->nodejs->go

Du coup les langages à typages forts tels que java ou c++,
bah je ne les ai jamais pratiqué,
les syntaxes ubuesques, très peu pour moi.

Lorsque appris go, j'ai souffert (sisi : ),
maintenant que j'ai passé le cap, très content de l'avoir fait par ailleurs,
je n'ai pas envie d'une syntaxe beaucoup plus complexe / riche comme le propose rust.
Là j'ai un compromis qui me plaît bien, il y a juste deux trois ajustements à opérer (generics?), selon moi.

La syntaxe rust a beaucoup de subtilités, a raison pour ce qu'il veut résoudre,
mais il reste tout de même ce genre d'exemple

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("username.txt");
    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };
    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

Je lis ce code, je crois comprendre, mais non, il reste des questions.

Je ne vois pas où est construit le retour Result<...>.

y a bien un return,
mais c'est pas au bon endroit (de ce que je crois savoir, évidemment!),
et le type ne correspond pas.
Alors il y a bien ces deux appels à Ok et Err, mais cela reste opaque.

Détail me direz vous, mais je déteste ce let, un appendice disgracieux et fort répétitif.

Toujours dans cet exemple s est mutable (2 fois!), car read_to_string doit pouvoir modifier le contenu,
mais a froid comme ça, je me demandes si Result<String, io::Error> est immutable,
ce qui amène à d'autres questions.

Le but de ces remarques n'est pas nécessairement d'obtenir une réponse précise,
mais plutôt de partager mon sentiment.
Avatar de mothsART mothsART - Membre régulier https://www.developpez.com
le 11/06/2017 à 14:13
Mh-cbon : ton approche top => bottom est bonne : beaucoup ne font pas l'effort et du coup progresse peu à mon sens.
Le passage à un typage fort est douloureux mais au final nécessaire car le gain est juste énorme : tu évites une paire de bug à l’exécution, le code est plus cohérent, t'as de meilleurs perfs etc.

Tu mets C et C++ dans le panier des vieux langages mais tu remarqueras que Go ne les remplace pas vraiment car il utilise un Garbage collector et une VM.
Pour moi, Go est un Java bis avec une syntaxe minimaliste, des gros avantages sur la programmation concurrente et des temps de compilation plus court.
Bref, rien de bien novateur à mon sens.

La réalité est que C et C++ sont pour l'instant encore indétrônable dans tous les domaines ou les perfs et la gestion de la mémoire sont critiques.
Rust étant plus ambitieux et par conséquent plus complexe est un réel candidat pour les remplacer.

Je dirais, pour ma part que le cap à passer pour Rust n'était pas vraiment la syntaxe (que je trouve élégante et intuitive) mais plus le borrowing. (et dans une moindre mesure les macros et closures)

Mais, comme tous les langages, il a des zones implicites qui nécessite apprentissage.
Ton exemple et ton incompréhension proviennent de là :

* la variable "f" et "let mut f" : f est dans un premier temps immutable : si le match réussi (passe par le Ok), cette variable est écrasé par le résultat et est converti en une variable mutable.
* le type Result est un peu particulier : il attend soit un objet succès ("Ok") avec le résultat (ici typé en String car on désire récupérer le contenu du fichier mais ça pourrais être n'importe quoi d'autre dans un autre contexte) ou un objet d'échec ("Err").
* le premier match (qui vérifie l'accès en lecture du fichier) a un retour explicite qui précise que si il détecte une erreur, il sort directement de la fonction (et par conséquent la variable mutable f n'est pas alimenté, la variable s n'est pas créé et le dernier match non executé.
* let permet de déclarer une variable, je ne vois pas trop ce qui te choques. (tu remplaces "var" par "let" dans ton passage de Go à Rust ou de NodeJS à Rust)
* en rust si la dernière ligne d'une fonction ne se termine pas par ";", on retourne implicitement le résultat.
C'est ce qui se passe dans le dernier match.
* s n'est pas déclaré 2 fois, elle est passé par référence dans la fonction "read_to_string".
* read_username_from_file renvoi une valeur qui peut parfaitement être mutable ou non selon la déclaration de ta variable de récupération :
Code : Sélectionner tout
1
2
3
4
let username_immutable = read_username_from_file();
// ou
let mut username_mutable = read_username_from_file();
Avatar de Uther Uther - Expert éminent https://www.developpez.com
le 12/06/2017 à 13:18
Citation Envoyé par mh-cbon Voir le message
Je ne vois pas où est construit le retour Result<...>.
Result est un cas particulier vu que comme c'est un élément central du langage, ses variant OK et Err sont inclus dans le prélude, ce qui fait que l'on peut les utiliser directement. Comme le type Result est utilisé partout, n'importe qui avec un minimum d'expérience dans le langage reconnais ça du premier abord.

Cependant, si tu tient à ce que ce soit clair que Ok et Err sont des variants du type énuméré Result, tu peux faire :
Code Rust : Sélectionner tout
1
2
3
4
    let mut f = match f {
        Result::Ok(file) => file,
        Result::Err(e) => return Result::Err(e),
    };
Avatar de Songbird_ Songbird_ - Rédacteur/Modérateur https://www.developpez.com
le 12/06/2017 à 18:09


Tout comme les variantes de l'enum Option<T>: Some(T) et None sont parfaitement comprises par le compilateur.

Sans expliciter la provenance des variantes ça donne:

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
fn main() {
    let foo = Some("Hello there!".to_owned());
    let bar = match foo{
        Some(content) => content,
        None => "Nothing, here.".to_owned(),
    };
    println!("bar={}", &bar);
}

Ce sont de petites subtilités, mais vraiment rien d'insurmontable. Ce ne sont pas des ressources "magiques", juste des raccourcis.
Avatar de tralloc tralloc - Membre actif https://www.developpez.com
le 15/06/2017 à 9:19
@mh-cbon
Eh bien moi c'est la deuxième fois que je me penche sur ce language.la première fois je l'ai trouvé trop complexe moi aussi.
Rien à voir avec les typages forts parce que je fais du JEE du C. Ni les typages faibles, car je ne suis pas trop mauvais en python.
Eh bien pour une deuxième fois, je commence à l'apprécier, et je crois qu'il vaut vraiment le coup.

La syntaxe est une chose, lorsqu'on a commencé à la comprendre il faut ensuite l'adopter. Une fois ce cap passé on peut profiter de sa richesse.
Avatar de tralloc tralloc - Membre actif https://www.developpez.com
le 15/06/2017 à 9:28
Je peux te filer un lien avec des exos pour pratiquer :
http://exercism.io/
mais avant il faut se taper de la doc, ce n'est pas un language simple.
Voici un tutoriel en français sur ce site.
http://guillaume-gomez.developpez.co...re-bases-rust/

Sinon il y a la doc officielle !
Avatar de Kennel sébastien Kennel sébastien - Membre averti https://www.developpez.com
le 15/06/2017 à 10:19
Bonjour tralloc,

C'est super de chercher à aider les autres :-).

Je voulais juste me permettre de te signaler un point :-p :
Tu as écrit « Ni les typages faibles, car je ne suis pas trop mauvais en python », or Python a un typage fort, en effet tu confonds typage statique et dynamique mais les trois langages ont des typages fort.

Des langages qui auraient des typages faibles sont par exemple : PHP, Javascript ou Ring.

Code : Sélectionner tout
print(5 + "5")
Ne travaille pas en Python, mais sous Ring avec :
Code : Sélectionner tout
See 5 + "5"
Tu obtiens le résultat 10 !

Rust a en fait un typage qui est inféré comme Go, Crystal, Swift…, c'est-à-dire que tu peux le rendre statique ou le laisser chercher le type pour toi alors que tu pourrais pas le faire en Python, en Python c'est lui qui cherche pour toi, il n'y a pas de déclaration de type.

Enfin pour ceux qui trouvent trop difficile Rust, peut-être vous tournez sur Go et revenir après sur Rust…
Avatar de tralloc tralloc - Membre actif https://www.developpez.com
le 15/06/2017 à 10:41
Oui je me suis trompé dans le mot que j'ai employé dsl
Je ne le referai plus promis
Avatar de Stéphane le calme Stéphane le calme - Chroniqueur Actualités https://www.developpez.com
le 21/07/2017 à 8:25
Rust 1.19 est disponible en version stable
et devient la première version à supporter union

Sur Windows, Rust s'appuie sur link.exe pour la liaison, que vous pouvez obtenir via Microsoft Visual C ++ Build Tools. Avec la publication récente de Visual Studio 2017, la structure de répertoire de ces outils a changé. En tant que tel, pour utiliser Rust, vous deviez rester sur les outils de 2015 ou utiliser une solution de contournement (comme l'exécution de vcvars.bat). Avec la version 1.19.0, rustc sait maintenant comment trouver les outils 2017, et ils fonctionnent sans solution de contournement.

Parmi les nouvelles fonctionnalités annoncées par l’équipe, Rust 1.19.0 est la première version qui supporte union :

Code Rust : Sélectionner tout
1
2
3
4
union MyUnion {
    f1: u32,
    f2: f32,
}

Les union sont comme enum, mais ils sont « non étiquetés ». Les enum disposent d’étiquette qui stocke la variante appropriée à l'exécution; Les union élident cette étiquette.

Puisque nous pouvons interpréter les données détenues dans l'union en utilisant la mauvaise variante et que Rust ne peut pas vérifier cela pour nous, cela signifie que la lecture ou l'écriture d'un champ d'union n'est pas sécurisée :

Code Rust : Sélectionner tout
1
2
3
4
5
let u = MyUnion { f1: 1 };
 
unsafe { u.f1 = 5 };
 
let value = unsafe { u.f1 };

Le pattern matching fonctionne également:

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
fn f(u: MyUnion) {
    unsafe {
        match u {
            MyUnion { f1: 10 } => { println!("ten"); }
            MyUnion { f2 } => { println!("{}", f2); }
        }
    }
}

Quand est-ce que les union peuvent s’avérer utiles ? Un cas d'utilisation majeur est l'interopérabilité avec C. Les API de C peuvent exposer les unions, ce qui facilite l’écriture des API qui vont intégrer ces bibliothèques.

Cette fonctionnalité a longtemps été attendue et, bien entendu, des améliorations sont prévues. Pour le moment, les union n’intègrent que les types copy et ne pourraient ne pas encore implémenter drop. « Nous prévoyons de lever ces restrictions à l'avenir », a assuré l’équipe.

Il est désormais possible de sortir (break) des boucles loop avec une valeur :

Code Rust : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
// ancien code
let x;
 
loop {
    x = 7;
    break;
}
 
// nouveau code
let x = loop { break 7; };

Parmi les fonctionnalités mineures, l’équipe note par exemple qu’il est possible de produire des tarballs compressés xz et qu’elle les préfère par défaut, ce qui rend le transfert de données plus petit et plus rapide. Les tarballs Gzip sont encore produits dans le cas où vous ne pouvez pas utiliser xz pour une raison quelconque.

Le compilateur peut maintenant démarrer sur Android. « Nous avons supporté depuis longtemps Android de différentes façons, ce qui continue d'améliorer notre support », a commenté l’équipe.

Côté compatibilité, l’équipe indique que « Lorsque nous allions vers Rust 1.0, nous avons fait une énorme pression pour vérifier tout ce qui était marqué comme stable et aussi instable. Nous avons négligé une chose, cependant : les drapeaux -Z. Le drapeau -Z permet au compilateur d’utiliser des drapeaux instables. Contrairement au reste de notre histoire de stabilité, vous pouvez toujours utiliser -Z sur une version stable de Rust. En avril 2016, dans Rust 1.8, nous avons émis un avertissement lors de l’usage de -Z sur la version stable ou bêta. Plus d'un an plus tard, nous résolvons ce trou dans notre histoire de stabilité en refusant -Z sur les versions stable et bêta. »

Stabilisations au niveau de la bibliothèque

La plus grande fonctionnalité de la nouvelle bibliothèque est l’ajout des macros eprint! et eprintln!. Elles fonctionnent exactement comme print! et println!, mais écrivent plutôt sur une erreur standard, par opposition à la sortie standard.

Autres nouvelles fonctionnalités :
  • String implémente désormais FromIterator<Cow<'a, str>> et Extend<Cow<'a, str>> ;
  • Vec implémente désormais From<&mut [T]> ;
  • Box <[u8]> implémente désormais From<Box<str>> ;
  • SplitWhitespace implémente désormais Clone.

Rust s'est traditionnellement positionné comme un « langage orienté vers l'expression », c'est-à-dire que la plupart des choses sont des expressions qui évaluent une valeur plutôt que des déclarations qui évaluent une valeur.

Source : annonce de Rust 1.19

Et vous ?

Utilisez-vous Rust ? Pour quel type de développement ? Qu'en pensez-vous ?
Quelle est la nouveauté qui vous a le plus intéressé ?
Offres d'emploi IT
Consultant technique ECM SharePoint (h-f)
Atos Intégration - Ile de France - Bezons
Recherche développeur - entrepreneur pour projet hyper excitant !
Wicross - Ile de France - Paris (75000)
Infographiste/webmestre/développeur
Ministère de l'intérieur/DGPN/SICoP - Ile de France - Paris (75008)

Voir plus d'offres Voir la carte des offres IT
Contacter le responsable de la rubrique Accueil