Getting the opposite of a variant using the '!' operator

Hi,

I would like to get the opposite of an enum variant using the '!' operator


let new_direction:Direction = !old_direction; 

enum Direction{
    North,
    South,
    East,
    West
}
impl Direction{
 fn opposite(&self)->Self{
...
}

I'm sure this question has been asked already but not getting any matches.

All of the operator override traits live in std::ops. For the ! operator, you want std::ops::Not, but unary minus (std::ops::Neg) might be more appropriate in this case.

3 Likes

Nice! Even a concrete example

Or just juse a method opposite() like you outlined in your example to make it more obvious.

6 Likes

I think ! would be confusing, but the suggestion of Neg instead is very natural: A "direction" is a unit vector, and the opposite direction is the negative of that vector.

Named functions are better than random choices of operators, but when there's an operator that's used across many fields for the exact behaviour in question, I think the operator is actually clearer.

5 Likes

Note that this requires some context:
In flat geometry like on a map (i.e. a Euclidean space), this is true for the same reason it is in a line graph: independent axes forming a coordinate system.

However, if you're working with a non-Euclidean geometry, things are different. For example, if we look at the surface of a sphere where a polar coordinate system might be more appropriate (Google Earth and the various GPS systems come to mind), then east can very locally be considered the opposite of west, but that doesn't generalize well because east is also where you end up if you go west and keep going.

In the former setting, it is easy to figure out that !Direction::East resolves to Direction::West.
But in the latter, it would confuse the living daylights out of me, and after reading the impl Not for Direction, I might well be tempted to remove that impl barring massive breakage.

1 Like

You're mixing vectors and points here. No matter how far west you go, you're still going west. You might have ended up at a position that could have been reached more easily by going east, but that's an entirely different type from a direction.

Using north/south would work a bit better -- after all, you can only go so far north before it's impossible to go north any more -- but that's also irrelevant for a ton of problems. See the Mercator projection, which is how it is to keep directions working, and just puts the pole infinitely far away and thus doesn't care about it, because people using that map never wanted to go there anyway.

So yes, you can have a problem where compass directions are a bad fit. But that problem also would almost certainly not be using the OP's enum, and thus impl Neg for Direction is thus also almost certainly fine.

2 Likes

NB: There’s nothing Rust- or programming-related in this comment

Geometry Pedantry

This isn’t necessarily true, because spherical coordinate systems are a bit odd. The most natural definition of “straight” on the surface of a sphere is the great-circle route; this is purely east-west at its maximum and minimum latitudes, but has a significant north-south component as it passes the equator.

However, this isn’t particularly relevant in this discussion: In order for these effects to appear, you need to be operating on a scale where the Direction type we’re discussing would be insufficient for other, more obvious, reasons.