Paradigmes 2023-2024 - TP 2

Etienne Lozes

Exercice 1. Itération sur des Vec<..>

Traduire en Rust la fonction Python suivante

def primes(N):
    res = [2]
    for i in range(3, N, 2):
        for j in res:
            if i % j == 0:
                break
            if j*j > i:
                res.append(i)
                break
    return res

Exercice 2. Généricité bornée par des traits

Ajoutez les traits bornant les types génériques nécessaires dans le code ci-dessous.

fn sum<T: ..., U: ... >(container: U) -> T {
    let mut res = Default::default();
    for x in container {
        res = res + x;
    }
    res
}

Exercice 3. Vecteurs de dimension 3

  1. Définissez le type Vec3D des vecteurs de dimension 3 (les coordonnées du vecteur seront représentées par des flotants 32 bits)
  2. Ajoutez un constructeur Vec3D::new(x, y, z).
  3. Implémentez automatiquement les traits Debug, Clone, Copy, et PartialEq pour Vec3D avec la macro #derive. Pourquoi ne peut-on pas implémenter le trait Eq?
  4. Implémentez le trait Display. Testez votre code avec le test ci-dessous (mettez ce code sous forme de test, et lancez-le depuis votre IDE ou avec cargo test, voir TP précédent). Pourquoi le test compile-t-il alors que nulle part vous n'avez défini de méthode .to_string() pour Vec3D?
let v = Vec3D::new(1.0, 2.0, 3.0);
assert_eq!(v.to_string(), "(1, 2, 3)".to_string());
  1. Implémentez le trait Add et testez.
let v1 = Vec3D::new(1.0, 2.0, 3.0);
let v2 = Vec3D::new(1.0, 1.0, 1.0);
assert_eq!((v1 + v2).to_string(), "(2, 3, 4)".to_string());
assert_eq!((v1 + 2.0).to_string(), "(3, 4, 5)".to_string());
assert_eq!((3.0 + v1).to_string(), "(4, 5, 6)".to_string());
  1. Implémentez le trait Mul et testez.
let v1 = Vec3D::new(1.0, 2.0, 3.0);
let v2 = Vec3D::new(1.0, -1.0, 2.0);
assert_eq!((v1 * v2), 5.0);
assert_eq!((v1 * 2.0).to_string(), "(2, 4, 6)".to_string());
assert_eq!((3.0 * v1).to_string(), "(3, 6, 9)".to_string());
  1. Pourquoi n'est-il pas possible d'étendre en plus le trait Mul pour noter v1 * v2 le produit vectoriel de v1 et v2?
// ceci n'est pas possible, pourquoi?
let v1 = Vec3D::new(1, 2, 3);
let v2 = Vec3D::new(1, -1, 2);
let v3 : f32 = v1 * v2; // 5 
let v4 : Vec3D = v1 * v2; // (7, 1, -3)
  1. Définissez un trait Mult (avec un t) le plus générique possible qui permette de surcharger une méthode mult pour Vec3D, et implémentez-le pour Vec3D.
let v1 = Vec3D::new(1.0, 2.0, 3.0);
let v2 = Vec3D::new(1.0, -1.0, 2.0);
let v3: f32 = v1.mult(v2);
let v4: Vec3D = v1.mult(v2);
assert_eq!(v3, 5.0);
assert_eq!(v4.to_string(), "(7, 1, -3)".to_string());
  1. Définissez un trait RMult (avec un t) le plus générique possible qui permette de surcharger une méthode rmult pour Vec3D, et implémentez-le pour Vec3D. N'implémentez pas RMult pour Vec3D, mais définissez plutôt un implémenteur qui génère automatiquement une implémentation de RMult pour toute implémentation de Mult.
let v1 = Vec3D::new(1.0, 2.0, 3.0);
let v2 = Vec3D::new(1.0, -1.0, 2.0);
let v3: f32 = v2.rmult(v1);
let v4: Vec3D = v2.rmult(v1);
assert_eq!(v3, 5.0);
assert_eq!(v4.to_string(), "(7, 1, -3)".to_string());
  1. Faites de Vec3D un type sur lequel on peut itérer.
let v = Vec3D::new(1, 2, 3);
for x in &v { println!(x) };
for x in &mut v { *x += 1 };
for x in v { println!(x) };
1
2
3
2
3
4