Introduction
Dans ce laboratoire, nous explorons le concept de DRY (Ne te répète pas) dans la programmation en utilisant des macros pour extraire les parties communes des fonctions et des suites de tests.
Note : Si le laboratoire ne spécifie pas de nom de fichier, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser
main.rs, le compiler et l'exécuter avecrustc main.rs &&./main.
DRY (Ne te répète pas)
Les macros permettent d'écrire du code DRY en extraisant les parties communes des fonctions et/ou des suites de tests. Voici un exemple qui implémente et teste les opérateurs +=, *= et -= sur Vec<T> :
use std::ops::{Add, Mul, Sub};
macro_rules! assert_equal_len {
// Le désignateur `tt` (arbre de jetons) est utilisé pour
// les opérateurs et les jetons.
($a:expr, $b:expr, $func:ident, $op:tt) => {
assert!($a.len() == $b.len(),
"{:?}: mismatch de dimension: {:?} {:?} {:?}",
stringify!($func),
($a.len(),),
stringify!($op),
($b.len(),));
};
}
macro_rules! op {
($func:ident, $bound:ident, $op:tt, $method:ident) => {
fn $func<T: $bound<T, Output=T> + Copy>(xs: &mut Vec<T>, ys: &Vec<T>) {
assert_equal_len!(xs, ys, $func, $op);
for (x, y) in xs.iter_mut().zip(ys.iter()) {
*x = $bound::$method(*x, *y);
// *x = x.$method(*y);
}
}
};
}
// Implémente les fonctions `add_assign`, `mul_assign` et `sub_assign`.
op!(add_assign, Add, +=, add);
op!(mul_assign, Mul, *=, mul);
op!(sub_assign, Sub, -=, sub);
mod test {
use std::iter;
macro_rules! test {
($func:ident, $x:expr, $y:expr, $z:expr) => {
#[test]
fn $func() {
for size in 0usize..10 {
let mut x: Vec<_> = iter::repeat($x).take(size).collect();
let y: Vec<_> = iter::repeat($y).take(size).collect();
let z: Vec<_> = iter::repeat($z).take(size).collect();
super::$func(&mut x, &y);
assert_eq!(x, z);
}
}
};
}
// Teste `add_assign`, `mul_assign` et `sub_assign`.
test!(add_assign, 1u32, 2u32, 3u32);
test!(mul_assign, 2u32, 3u32, 6u32);
test!(sub_assign, 3u32, 2u32, 1u32);
}
$ rustc --test dry.rs && ./dry
running 3 tests
test test::mul_assign... ok
test test::add_assign... ok
test test::sub_assign... ok
test result: ok. 3 passed
0 failed
0 ignored
0 measured
Résumé
Félicitations! Vous avez terminé le laboratoire DRY (Ne te répète pas). Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.