Je me disais que tu dirais ça... C’est pas juste un gros mix. Le style est très cohérent, on a de l’inférence de type, on a une structure match qui est un switch mais sans avoir besoin d’utiliser break, qui vérifie et l’oblige à traiter tous les cas possibles:
match(3) {
x if x < 0 => {},
x if x > 0 => {}
}
donne
test.rs:2:1: 5:2 error: non-exhaustive patterns
test.rs:2 match(3) {
test.rs:3 x if x < 0 => {},
test.rs:4 x if x > 0 => {}
test.rs:5 }
Il n’y a pas de pointeurs «null» mais un type spécial, Option:
let x = ma_fonction_qui_peut_renvoyer_null_en_c_ou_un_int();
match x {
None => { /* On traite le cas où la fonction ci-dessus ne nous a rien renvoyer d’intéressant */ },
Some(x) if x < 0 => { /* cas où x est inférieur à zéro */ },
Some(2..3) => { /* On traite le cas de deux à trois*/ },
Some(x) if x > 0 => { /* travail sur x dans les autres cas */ },
_ => { /* Tous les autres cas */ }
}
Les structures de contrôles sont toutes des déclarations, ce qui permet de faire des choses intéressantes, par exemple en reprenant l’exemple du dessus, on ferait plutôt:
let x = match {
Some(x) => { x }, // pas de ; à la fin donc le «return» est implicite
None => { /* On renvoie une valeur par défaut */ }
}
ou
let x = nombre_negatif_ou_positif();
x = if x > 0 { x } else { -x };
On a des pointeurs dont l’objet pointé est géré par un ramasse-miette par tâche ce qui fait que l’on arrête pas le programme globalement, mais la plupart du temps on utilise un objet possédé qui a la durée de vie de son pointeur. Il y a aussi un système de référence pour pouvoir prendre en paramètre de manière indifférente l’un ou l’autre pointeur pré-cité.
On a des tâches qui permettent la parallélisation vraiment facilement, c’est vraiment facile de les faire communiquer avec des tubes comme en C mais totalement sûr. C’est bien simple, un programme Rust ne peut pas faire une erreur de segmentation a moins d’un bug dans le compilateur ou dans la bibliothèque standard (il est possible d’écrire du code non-sûr — unsafe — pour certaines choses mais il doit être indiqué au compilateur).
On a des clôtures, on peut faire des trucs génériques facilement, on a un système léger de macros, un système de formatage de texte aussi puissant que celui de Python. Il n’y a pas de classes, on a des struct sur lesquelles on implante des méthodes, on a des traits (des interface en Java, il y a aussi un concept similaire en Haskell). Le style de déclaration de fonctions ressemble au Python avec annotations.
trait Test {
// le &self indique que ce n’est pas une méthode statique, le ~ sert à indiquer que la str possédée
fn fonction_de_test(&self, quelque_chose: uint) -> ~str;
}
struct Machine {
x: uint,
y: uint
}
impl Machine {
fn new(x: uint, y: uint) -> Machine {
Machine {
x: x *2 + 3,
y: y - 5
}
}
}
impl Test for Machine {
fn fonction_de_test(&self, liste: ~[int], quelque_chose: uint) -> ~str {
let x = (self.x - self.y) * quelque_chose;
for i in liste.iter() {
}
x.to_str()
}
}
fn main() {
let x = Machine::new(2, 5);
println!("Résultat: {}", x.fonction_de_test(6));
}
(le plus incroyable, c’est que j’ai mis n’importe quoi et que le résultat est... 42)
On peut implanter des méthodes et des traits sur des types de base. Les noms des types sont en général bien choisis et courts (vec pour vecteur, to_str() à comparer au ToString de Java).
Il est très facile d’utiliser des fonctions de bibliothèques C et d’exporter ses fonctions pour qu’on puisse les utiliser depuis un langage qui peut appeler des fonctions C (c’est à dire quasiment tous).
J’ai sans doute oublier des tas de trucs, mais bon je vais arrêter là parce que sinon on y est pour deux heures encore! :p
[^] # Re: nosql embarqué ?
Posté par ariasuni . En réponse à la dépêche SQLite 3.8.0 : n'ayez pas peur du zéro. Évalué à 2.
Je me disais que tu dirais ça... C’est pas juste un gros mix. Le style est très cohérent, on a de l’inférence de type, on a une structure match qui est un switch mais sans avoir besoin d’utiliser break, qui vérifie et l’oblige à traiter tous les cas possibles:
donne
Il n’y a pas de pointeurs «null» mais un type spécial, Option:
Les structures de contrôles sont toutes des déclarations, ce qui permet de faire des choses intéressantes, par exemple en reprenant l’exemple du dessus, on ferait plutôt:
ou
On a des pointeurs dont l’objet pointé est géré par un ramasse-miette par tâche ce qui fait que l’on arrête pas le programme globalement, mais la plupart du temps on utilise un objet possédé qui a la durée de vie de son pointeur. Il y a aussi un système de référence pour pouvoir prendre en paramètre de manière indifférente l’un ou l’autre pointeur pré-cité.
On a des tâches qui permettent la parallélisation vraiment facilement, c’est vraiment facile de les faire communiquer avec des tubes comme en C mais totalement sûr. C’est bien simple, un programme Rust ne peut pas faire une erreur de segmentation a moins d’un bug dans le compilateur ou dans la bibliothèque standard (il est possible d’écrire du code non-sûr — unsafe — pour certaines choses mais il doit être indiqué au compilateur).
On a des clôtures, on peut faire des trucs génériques facilement, on a un système léger de macros, un système de formatage de texte aussi puissant que celui de Python. Il n’y a pas de classes, on a des struct sur lesquelles on implante des méthodes, on a des traits (des interface en Java, il y a aussi un concept similaire en Haskell). Le style de déclaration de fonctions ressemble au Python avec annotations.
(le plus incroyable, c’est que j’ai mis n’importe quoi et que le résultat est... 42)
On peut implanter des méthodes et des traits sur des types de base. Les noms des types sont en général bien choisis et courts (vec pour vecteur, to_str() à comparer au ToString de Java).
Il est très facile d’utiliser des fonctions de bibliothèques C et d’exporter ses fonctions pour qu’on puisse les utiliser depuis un langage qui peut appeler des fonctions C (c’est à dire quasiment tous).
J’ai sans doute oublier des tas de trucs, mais bon je vais arrêter là parce que sinon on y est pour deux heures encore! :p
Écrit en Bépo selon l’orthographe de 1990