Hacker News new | ask | show | jobs
by fluffything 2456 days ago
Try doing any of this with variant and visit

    enum A { Foo{ x: i32, y: f32 }, Bar(B), Baz([u32; 4]), Moo(i32), Mooz(i32) }
    struct B { z: f32, w: (f64, f32) }

    let b = B { z: 42.0, ..}; // create a b with z == 42 and default w
    let B{ w: (first, _), .. } = b; // get B.w.0 field
    let a = A::Foo{ x: 42.0, ..};
    if let A::Bar(Bar { z, ..}) = a {
      // if a is an A::Bar, get b.z field of A::Bar(b)
    }
    if let A::Baz([0, 1, 2, 3]) = a {
      // if a is an A::Baz containing an array 
      // with value [0, 1, 2, 3]
    }
    match a {
        A::Moo(1..3 @ v) => {
           // if a is an A::Moo where x in A::Moo(x) is in range [0, 3) and put the value in the local v variable
        }
        A::Moo(x) | A::Mooz(x) => { 
           // Either A::Moo or A::mooz, gives you the value of x
        }
        // ERROR: I forgot to match some patterns
    }

    foo(b);

    fn foo(B{ z, ..}: B) -> f64 { 
      // get the z field of the first function argument
      z
    }
What in Rust are one liners, and can be used anywhere (let bindings, constructors, match, if-let, while-let, function arguments, ...) is a pain to write in C++ using `std::visit` and `std::variant`. The error messages of `std::visit` + `std::variant` are quite bad as well. And well, then there are also other fundamental problems with variant like `variant<int>` having two variants, `variant<int, int>` having 3 variants, but you can't reach the second `int`, etc.

You can translate all the code above to C++ to use std::visit + std::variant instead. I personally find that C++ is unusable for programming like this, and almost never use std::variant in C++ as a consequence, while I use ADTs in Rust all the time.