Accessing a struct inside an enum - struct

How do I access field c inside struct of type B_ inside enum of type A in this case?
enum A {
B(B_),
D(D_)
}
enum D_ { D_1, D_2 }
struct B_ {
c: Vec<i32>,
}
Obvious stuff like this doesn't work:
let y = A::B;
y.c = Vec::new();

I think the first problem is that what you really want is y to be of type A, so it cannot have a field named c in the first place. y can be A::B or A::D. Only if y is an A::B variant, then you can get the B_ object inside the variant and then get the c.
The second problem in your code is that you are not initializing y to be an A::B variant. The expression A::B is of type fn(B_) -> A {A::B} which is a kind of constructor function (automagically generated by the compiler) for A enums.
The following code initialize y correctly and get c:
enum A {
B(B_),
D(D_)
}
enum D_ { D_1, D_2 }
struct B_ {
c: Vec<i32>,
}
fn main() {
let y = A::B( B_ { c : Vec::new() });
// Check if y is an A::B, so we can get the B_ object inside
// by deconstruction. Then we can get c.
if let A::B(b_) = y {
println!("{:?}", b_.c);
}
}
Maybe you thought that A::B is a kind of B type defined "inside" A, which is not how enums work is Rust.

Related

How do I use circular dependencies in structs in Rust?

I have two structs that depend on each other. In C++ I would do this with pointers, I'm trying to figure out how to do this in Rust. I've tried using Box and Rc so far, I would think since Rc is a reference counter it should be able to handle this, but it's giving me an error.
Here is a simple code example:
struct A {
b : Rc<B>
}
struct B {
a : Option<Rc<A>>
}
fn main() {
let mut b = B {
a : None
};
let a = A {
b: Rc::new(b)
};
b.a = Some(Rc::new(a));
}
Here is the error I get from it:
20 | let mut b = B {
| ----- move occurs because `b` has type `B`, which does not implement the `Copy` trait
...
25 | b: Rc::new(b)
| - value moved here
...
28 | b.a = Some(Rc::new(a));
| ^^^ value partially assigned here after move
What is the correct way to do this type of relationship in Rust?
You shouldn't use Rc::new twice for an object. The correct way is to use Rc::new once, and clone it as needed. What's more, in order to mutate b behind a Rc, you should combine it with RefCell.
use std::cell::RefCell;
use std::rc::Rc;
struct A {
b: Rc<B>,
}
struct B {
a: RefCell<Option<Rc<A>>>,
}
fn main() {
let b = Rc::new(B {
a: RefCell::new(None),
});
let a = Rc::new(A { b: b.clone() });
*b.a.borrow_mut() = Some(a.clone());
assert!(b.a.borrow().is_some());
}
But even you do like this, you still make an memory leak, which is bad. A better way is to use Weak and Rc::new_cyclic to make cycles.
use std::rc::{Rc, Weak};
struct A {
b: Rc<B>,
}
struct B {
a: Weak<A>,
}
fn main() {
let a: Rc<A> = Rc::new_cyclic(|a| A {
b: Rc::new(B { a: a.clone() }),
});
let b: Rc<B> = a.b.clone();
}
This avoids use of cells and memory leak.
This is compiling (this is single threaded example)
use std::cell::RefCell;
use std::rc::Rc;
// make a cycle: struct A owning struct B and struct B owning struct A
struct A {
b : Rc<RefCell<B>>
}
struct B {
a : Option<Rc<RefCell<A>>>
}
fn main() {
// init b with None
let b = Rc::new(RefCell::new(B { a: None }));
// init a with b
let a = Rc::new(RefCell::new(A { b: Rc::clone(&b) }));
// set b.a to a
b.borrow_mut().a = Some(Rc::clone(&a));
}
You use Rc to have mutiple ownership. So that you can both move b to a and then still address it as b and even try change it.
Rc is read only so use RefCell so that you hide the fact that you change things.
There is another example of cycle in Rust book
https://doc.rust-lang.org/book/ch15-06-reference-cycles.html

How can I make a struct with a constant parameter that may be only known at runtime?

At the moment I have my own integer type which works like this:
let x = Integer::new(12);
Now I want to work with integers mod n (and be able to properly overload binary operations), so I would like something that works like this:
let X = IntegerMod<11>;
let x = X::new(12);
Then 12 is reduced mod 11 so x = 1.
I can do this using const generics but then the modulus needs to be known at compile time and I can't have a function output some IntegerMod<n> where n is determined at runtime (which I would like to have).
What is the best way to get this behavior?
You could use a sort of factory function approach, where an IntegerMod instance can be created giving it the modulus value, which acts as the factory for Integer values. The underlying type can be generic.
Usage could look something like this:
fn main()
{
let im = IntegerMod::fact(5);
println!("{:?}", im.new(111)); // Prints `Integer { value: 1 }`.
}
IntegerMod as an Integer producer.
use std::ops::Rem;
struct IntegerMod<T>
{
modulus: T,
}
impl<T> IntegerMod<T>
where
T: Rem<Output = T> + Copy,
{
fn fact(modulus: T) -> Self
{
IntegerMod { modulus }
}
// Maybe name this something different. But keeping with the example...
fn new(&self, value: T) -> Integer<T>
{
Integer::new(value % self.modulus)
}
}
Integer:
#[derive(Debug)]
struct Integer<T>
{
value: T,
}
impl<T> Integer<T>
{
fn new(value: T) -> Self
{
Integer { value }
}
}

What's the difference between One::one() vs 1

What is the difference between One::one() and just the number 1? Is there any difference?
One::one() is intended to be used in generic code where we do not know what is the exact type of the numerical value.
It could be 1_i32, 1.0, 1_u8... depending on the exact type the One trait is bound to.
Thanks to the useful comments below, here is a minimal example to try to illustrate better (although it's late).
Trying to initialise some variables with 1 works if they are considered as integers (a and c here).
On the other hand, this does not work for a real (b here); 1.0 must be used instead.
When it comes to our own non-primtive type (Thing here), the One trait helps providing a value considered as 1 (note that the Mul trait must be implemented on this type too).
The One trait becomes really useful in a generic function in which the exact type is not already known when we need the 1 value (like mul_one() here).
use num_traits::One;
use std::ops::Mul;
#[derive(Debug)]
struct Thing {
member: String,
}
// Mul<Self, Output = Self> is required for One
impl Mul for Thing {
type Output = Self;
fn mul(
self,
rhs: Self,
) -> Self {
Self {
member: self.member + "×" + &rhs.member,
}
}
}
impl One for Thing {
fn one() -> Self {
Self {
member: "one".to_owned(),
}
}
}
fn mul_one<T: One>(arg: T) -> T {
// arg * 1 // error: expected type parameter `T`, found integer
arg * T::one()
}
fn main() {
let a: i32 = 1;
// let b: f64 = 1; // error: expected `f64`, found integer
let b: f64 = 1.0;
let c: u8 = 1;
let d = Thing::one();
println!("{:?} {:?} {:?} {:?}", a, b, c, d);
let e = mul_one(a);
let f = mul_one(b);
let g = mul_one(c);
let h = mul_one(d);
println!("{:?} {:?} {:?} {:?}", e, f, g, h);
}
/*
1 1.0 1 Thing { member: "one" }
1 1.0 1 Thing { member: "one×one" }
*/

What is this strange syntax where an enum variant is used as a function?

Below is the example given by the mod documentation of syn::parse.
enum Item {
Struct(ItemStruct),
Enum(ItemEnum),
}
struct ItemStruct {
struct_token: Token![struct],
ident: Ident,
brace_token: token::Brace,
fields: Punctuated<Field, Token![,]>,
}
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
input.parse().map(Item::Struct) // <-- here
} else if lookahead.peek(Token![enum]) {
input.parse().map(Item::Enum) // <-- and here
} else {
Err(lookahead.error())
}
}
}
Is input.parse().map(Item::Struct) a valid normal Rust syntax (appears not as Item::Struct is not a function), or is it a kind of special syntax for proc_macro libs? If the latter is the case, is there a documentation of the proc_macro specific syntax rules?
This syntax is standard Rust syntax. You can use tuple struct or tuple struct-like enum variants as functions. See this small example:
enum Color {
Str(String),
Rgb(u8, u8, u8),
}
struct Foo(bool);
// Use as function pointers (type annotations not necessary)
let f: fn(String) -> Color = Color::Str;
let g: fn(u8, u8, u8) -> Color = Color::Rgb;
let h: fn(bool) -> Foo = Foo;
In the next example, those functions are directly passed to another function (like Option::map) (Playground):
// A function which takes a function
fn string_fn<O, F>(f: F) -> O
where
F: FnOnce(String) -> O,
{
f("peter".to_string())
}
string_fn(|s| println!("{}", s)); // using a clojure
string_fn(std::mem::drop); // using a function pointer
// Using the enum variant as function
let _: Color = string_fn(Color::Str);
You can find out more about this feature, in this chapter of the book.

Matching with less boilerplate

I have nested structures of enums, ie. enum X has a variant which contains enum Y etc. Is there any way to access fields eg x.y.z with a runtime error if x.y.z doesn't exist (eg, x is of wrong variant). Furthermore is this a reasonably moral thing to do, or is there a better alternative, without match statements everywhere? Efficiency is not so important, though it would be good to make it as cheap as possible.
It is not possible to access nested enums with dots syntax, but you can use if let:
pub enum X {
A(Y),
B(Z)
}
pub enum Y {
C,
D(u32)
}
pub enum Z {
E
}
fn main() {
let x = X::A(Y::D(12));
if let X::A(Y::D(n)) = x {
println!("Got it: {}", n);
} else {
println!("Nope");
}
}
(try it here)
if let makes the code arguably more concise than match. Naturally, this is as efficient as match.
Given these definitions:
enum X {
Variant(Y),
…
}
enum Y {
Variant(Z),
…
}
struct Z;
You can use if let with deep patterns as one way:
if let X::Variant(Y::Variant(ref z) = x {
// Use z
} else { // And these two lines are,
panic!(); // of course, optional.
}
Or you could define methods (panicking is not a good idea, though; having such methods return Option is much more common, as is shown in rustc_serialize’s Json enum, for example), but it will still leave you with comparatively ugly code, probably):
impl X {
fn y(&self) -> &Y {
match *self {
Variant(ref y) => y,
_ => panic!(),
}
}
}
// Ditto for Y.z()
let z = x.y().z();

Resources