Transfert de propriété
fn main() {
let v = Vec::new();
let mut w = remplir(v);
println!("w contient {} éléments : {:?}", w.len(), w);
w.push(88);
println!("w contient {} éléments : {:?}", w.len(), w);
// println!("v contient {} éléments : {:?}", v.len(), v); // interdit
}
fn remplir(mut v: Vec<i32>) -> Vec<i32> {
v.extend([22, 44, 66]);
_id().unwrap()]);
v
}
Variante avec emprunt mutable
fn main() {
let mut v = Vec::new();
remplir_ref(&mut v);
println!("v contient {} éléments : {:?}", v.len(), v);
v.push(88);
println!("v contient {} éléments : {:?}", v.len(), v);
}
fn remplir_ref(v: &mut Vec<i32>) {
v.extend([22, 44, 66]);
}
Variante avec clonage
fn main() {
let mut v = Vec::new();
let mut w = remplir_clone(v.clone());
println!("w contient {} éléments : {:?}", w.len(), w);
w.push(88);
println!("w contient {} éléments : {:?}", w.len(), w);
}
fn remplir_clone(mut v: Vec<i32>) -> Vec<i32> {
v.extend([22, 44, 66]);
v
}
Vraiante sans paramètre
fn main() {
let mut v = construire();
println!("v contient {} éléments : {:?}", v.len(), v);
v.push(88);
println!("v contient {} éléments : {:?}", v.len(), v);
}
fn construire() -> Vec<i32> {
vec![22, 44, 66]
}
Manipulation de références
fn main() {
let mut x = 100;
let r1 = &mut x;
*r1 += 100;
let r2 = &mut x;
*r2 += 1000;
assert_eq!(x, 1200);
let texte = "Rust is great!".to_string();
dernier_caractere(&texte);
majuscules(texte);
}
fn dernier_caractere(s: &String) -> char {
s.chars().last().unwrap()
}
fn majuscules(mut s: String) {
s.make_ascii_uppercase();
println!("{}", s);
}
Durées de vie
struct Livre<'a> {
auteur: &'a str,
titre: &'a str,
}
fn main() {
let a = String::from("abcd");
let b = "xyz";
let plus_long = le_plus_long(&a, b);
println!("La plus longue chaîne est '{}'", plus_long);
let nom = String::from("Jill Smith");
let titre = String::from("Fish Flying");
let livre = Livre { auteur: &nom, titre: &titre };
println!("{} par {}", livre.titre, livre.auteur);
}
fn le_plus_long<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
Pointeurs intelligents
Box
#[derive(Debug, PartialEq)]
enum Liste {
Cons(i32, Box<Liste>),
Vide,
}
fn main() {
let vide = creer_vide();
let pleine = creer_pleine();
println!("Liste vide : {:?}", vide);
println!("Liste pleine : {:?}", pleine);
assert_eq!(vide, Liste::Vide);
assert_ne!(vide, pleine);
}
fn creer_vide() -> Liste { Liste::Vide }
fn creer_pleine() -> Liste { Liste::Cons(1, Box::new(Liste::Vide)) }
Rc
use std::rc::Rc;
#[derive(Debug)]
struct Soleil {}
#[derive(Debug)]
enum Planete {
Mercure(Rc<Soleil>), Venus(Rc<Soleil>), Terre(Rc<Soleil>),
Mars(Rc<Soleil>), Jupiter(Rc<Soleil>), Saturne(Rc<Soleil>),
Uranus(Rc<Soleil>), Neptune(Rc<Soleil>),
}
impl Planete {
fn saluer(&self) { println!("Salut depuis {:?}!", self) }
}
fn main() {
let soleil = Rc::new(Soleil {});
println!("compteurs = {}", Rc::strong_count(&soleil));
let mercure = Planete::Mercure(Rc::clone(&soleil));
println!("compteurs = {}", Rc::strong_count(&soleil));
mercure.saluer();
macro_rules! planete {
($n:ident, $var:ident, $p:path) => {
let $var = $p(Rc::clone(&soleil));
println!("compteurs = {}", Rc::strong_count(&soleil));
$var.saluer();
};
}
planete!(venus, v, Planete::Venus);
planete!(terre, t, Planete::Terre);
planete!(mars, m, Planete::M);
planete!(jupiter, j, Planete::Jupiter);
planete!(saturne, s, Planete::Saturne);
planete!(uranus, u, Planete::Uranus);
planete!(neptune, n, Planete::Neptune);
assert_eq!(Rc::strong_count(&soleil), 9);
drop(n);
drop(u);
drop(s);
drop(j);
drop(m);
drop(t);
drop(v);
drop(mercure);
assert_eq!(Rc::strong_count(&soleil), 1);
}
Arc
use std::sync::Arc;
use std::thread;
fn main() {
let valeurs: Vec<_> = (0..100u32).collect();
let partage = Arc::new(valeurs);
let mut taches = vec![];
for decalage in 0..8 {
let nombres = Arc::clone(&partage);
taches.push(thread::spawn(move || {
let somme: u32 = nombres.iter()
.filter(|&n| n % 8 == decalage)
.sum();
println!("Somme décalage {} = {}", decalage, somme);
}));
}
for t in taches { t.join().unwrap(); }
}
Cow
use std::borrow::Cow;
fn abs_tout<'a>(entree: &'a mut Cow<'_, [i32]>) -> &'a mut Cow<'_, [i32]> {
for i in 0..entree.len() {
if entree[i] < 0 {
entree.to_mut()[i] = -entree[i];
}
}
entree
}
fn main() {
let s = [0, 1, 2];
let mut c = Cow::from(&s[..]);
match abs_tout(&mut c) {
Cow::Borrowed(v) => println!("Emprunt : {:?}", v),
_ => panic!("devrait être emprunté"),
}
let s = [-1, 0, 1];
let mut c = Cow::from(&s[..]);
match abs_tout(&mut c) {
Cow::Owned(v) => println!("Copié : {:?}", v),
_ => panic!("devrait être copié"),
}
let v = vec![-1, 0, 1];
let mut c = Cow::from(v);
match abs_tout(&mut c c) {
Cow::Owned(v) => println!("Déjà propriétaire : {:?}", v),
_ => panic!("devrait être propriétaire"),
}
}
Concurrence
Lancement simple
use std::thread;
use std::time::Duration;
fn main() {
let mut handles = vec![];
for i in 0..10 {
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_millis(250));
println!("thread {} terminé", i);
}));
}
let mut finis = 0;
for h in handles {
h.join().unwrap();
finis += 1;
}
assert_eq!(finis, 10);
}
Partage d'état avec Mutex
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
struct Compteur {
termines: u32,
}
fn main() {
let cpt = Arc::new(Mutex::new(Compteur { termines: 0 }));
let mut taches = vec![];
for _ in 0..10 {
let c = Arc::clone(&cpt);
taches.push(thread::spawn(move || {
thread::sleep(Duration::from_millis(250));
c.lock().unwrap().termines += 1;
}));
}
for t in taches {
t.join().unwrap();
println!("tâches terminées : {}", cpt.lock().unwrap().termines);
}
}
Canal MPSC
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
struct File {
taille: u32,
debut: Vec<u32>,
fin: Vec<u32>,
}
impl File {
fn nouvelle() -> Self {
File {
taille: 10,
debut: vec![1, 2, 3, 4, 5],
fin: vec![6, 7, 8, 9, 10],
}
}
}
fn envoyer(f: File, tx: mpsc::Sender<u32>) {
let f = Arc::new(f);
let f1 = Arc::clone(&f);
let tx1 = tx(tx.clone());
thread::spawn(move || {
for &v in &f1.debut {
tx1.send(v).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
thread::spawn(move || {
for &v in &f.fin {
tx.send(v).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
}
fn main() {
let (tx, rx) = mpsc::channel();
let file = File::nouvelle();
let longueur = file.taille;
envoyer(file, tx);
let mut recus = 0;
for v in rx {
println!("Reçu : {}", v);
recus += 1;
}
println!("Total reçu : {}", recus);
assert_eq!(recus, longueur);
}