Tomasz Bawor
Tomasz Bawor

Reputation: 1647

Constructor with if returning wrong structure

I am creating simple generic structure representing edge in a graph, and I wanted constructor to switch arguments so the lower would be first.

pub type Index = u16;
pub type Cost = u32;

pub struct Edge<T> {
    first: Index,
    second: Index,
    weight: T,
}

impl<T> Edge<T> {
    pub fn new(first: Index, second: Index, weight: T) -> Self {
        return if second > first {
            Edge { second, first, weight }
        } else {
            Edge { first, second, weight }
        }
    }
}

However I am unable to make it work since my tests results in error.

 #[test]
    fn should_initialize_with_lover_value_first() {
        // given
        let lower: Index = 234;
        let high: Index = 444;
        let cost: Cost = 34;

        // when
        let edge: Edge<Cost> = Edge::new(high, lower, cost);

        // then
        assert_eq!(edge.first, lower, "edge.first = {}, expected = {}", edge.first, lower);
        assert_eq!(edge.second, high, "edge.second = {}, expected = {}", edge.second, high);
    }

I got error :

thread 'types::generic::edge::tests::should_initialize_with_lover_value_first' panicked at 'assertion failed: `(left == right)`
  left: `444`,
 right: `234`: edge.first = 444, expected = 234', src/types/generic/edge.rs:35:9

Am I missing some kind of werid rust behaviour that I am not aware of?

Upvotes: 0

Views: 177

Answers (2)

Sam Estep
Sam Estep

Reputation: 13294

Rust lets you pun on the variable name when it's the same as the field name. So this:

Edge { second, first, weight }

is equivalent to this:

Edge {
    second: second,
    first: first,
    weight: weight,
}

And this:

Edge { first, second, weight }

is equivalent to this:

Edge {
    first: first,
    second: second,
    weight: weight,
}

As you can see, they both are equivalent to each other.

If you want to flip first and second then you can do this instead:

Edge {
    first: second,
    second: first,
    weight,
}

Upvotes: 5

Lukas
Lukas

Reputation: 149

You might want to write it like this, since your code does not change the places where first and second are located:

pub fn new(first: Index, second: Index, weight: T) -> Self {
    return if second > first {
        Edge { first: second, second: first, weight }
    } else {
        Edge { first, second, weight }
    }
}

Upvotes: 1

Related Questions