37

How can I port this C++ code to Rust:

auto sgnR = (R >= 0.) ? 1. : -1.;

I have seen some examples with the match keyword, but I don't understand how it works.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
  • 2
    https://github.com/rust-lang/rfcs/issues/1362 – Barmar Jul 14 '17 at 00:04
  • 3
    Google "rust ternary operator" and you'll find a bunch of hits. – Barmar Jul 14 '17 at 00:04
  • @Baum This question requires understanding of both Rust and C++ so it is one of the very few questions that should have both tags. I do, however, think it should be closed for *other* reasons. – Galik Jul 14 '17 at 00:10
  • 1
    @Galik Nah, tags are for finding relevant stuff. No one with a C++ question will want to find this question, so it should not have the tag. It's not a C++ question, but solely a rust question. (Also, I don't get the "it should be closed for *other* reasons" part, that appears to pretty orthogonal to the whole tagging issue.) – Baum mit Augen Jul 14 '17 at 00:14
  • @BaummitAugen But how do you expect a pure Rust programmer to convert code from a language he doesn't understand? Some knowledge of C++ is required. If people don't want to find this question then it should rather be closed than mistagged – Galik Jul 14 '17 at 00:33
  • 1
    @Galik *"But how do you expect a pure Rust programmer to convert code from a language he doesn't understand?"* I don't expect people who don't know this syntax to answer this question at all, but that does not make this a question about C++. *"If people don't want to find this question then it should rather be closed than mistagged"* People looking for *C++* answers won't want to find it. People looking of Rust answer probably will. Thus it should be tagged [rust], but not [c++]. – Baum mit Augen Jul 14 '17 at 11:58
  • i just wanted to say that... coming from C/C++, the "match" statement is like a "super ternary" operator.... in that the ternary operator only allows to check a boolean to continue to one of two values... with match you can check a pattern against an input, and continue to many many different values. – don bright Jul 07 '18 at 20:55

3 Answers3

90

Rust does not have the ternary operator because it's not needed. Almost everything evaluates to some value, and if / else expressions are no exception:

let r = 42.42;
let sgn_r = if r >= 0. { 1. } else { -1. };

You'll note that I've also changed your variable names to be idiomatic Rust. Identifiers use snake_case.

Do not be confused by the ? operator that Rust does have. This is called the "try operator" and is used to propagate errors.


Specifically for this code, it's likely you should use f64::signum:

let r = 42.42_f64;
let sgn_r = r.signum();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
10

You can use bool::then or in this case, the non-lazy bool::then_some to accomplish the same thing:

let sgn_r = (r >= 0).then_some(1).unwrap_or(-1);

An if/else statement is probably better for readability, but this may be nicer in certain cases.

Ibraheem Ahmed
  • 11,652
  • 2
  • 48
  • 54
0

I like to implement a similar construct using a trait:

pub trait IfElse {
    fn ifelse<T>(&self, iftrue: T, iffalse: T) -> T;
}

impl IfElse for bool {
    fn ifelse<T>(&self, iftrue: T, iffalse: T) -> T {
        if *self { iftrue }
        else { iffalse }
    }
}

Then it can be used like this:

let sng_r = (r >= 0).ifelse(1, -1);
Lord Bo
  • 3,152
  • 3
  • 15
  • 22