Reputation: 3080
I'm newbie in Rust from Python. I believe it's a basic question, but I am too new to find the answer by keywords like Type Casting Option.
In Python, to make the type checker know return type is not Optional[int] + int
, we can address assert
logic to enforce the type checker know x
will never be None
after line assert
.
from typing import Optional
def add_one(x: Optional[int] = None) -> int:
if x is None:
x = 0
assert x is not None
return x + 1
if __name__ == '__main__':
add_one(0) # 1
add_one() # 1
add_one(999) # 1000
In Rust, assuming the interface is same, how do achieve the same thing? Namely, how to make compiler know the type of x
is not Option
anymore?
fn add_one(mut x: Option<i32>) -> i32 {
if x == None {
x = Some(0);
}
return x + 1;
}
fn main() {
add_one(Some(0));
add_one(None);
add_one(Some(999));
}
Here's the error message:
error[E0369]: binary operation `+` cannot be applied to type `std::option::Option<i32>`
--> tmp.rs:5:14
|
5 | return x + 1;
| - ^ - {integer}
| |
| std::option::Option<i32>
|
= note: an implementation of `std::ops::Add` might be missing for `std::option::Option<i32>`
Note that I've tried things like adding another variable with type i32 (let y: i32 = x;
), but it didn't work either with following message.
error[E0308]: mismatched types
--> tmp.rs:5:22
|
5 | let y: i32 = x;
| ^ expected i32, found enum `std::option::Option`
|
= note: expected type `i32`
found type `std::option::Option<i32>`
Upvotes: 4
Views: 6111
Reputation: 42207
Namely, how to make compiler know the type of x is not Option anymore?
Rust's type checker doesn't have to be compatible with somewhat dodgy usage patterns, so the way to do that is to redefine x as not an option anymore e.g.:
fn add_one(mut x: Option<i32>) -> i32 {
let x = if let Some(v) = x {
v
} else {
0
};
return x + 1;
}
or the uglier and less efficient (but maybe closer to Python):
fn add_one(mut x: Option<i32>) -> i32 {
let x = if x == None {
0
} else {
x.unwrap()
};
return x + 1;
}
Note that you don't have to shadow x
, so you could just as well let y
instead. It would probably be cleaner here.
But as Boiethios pointed out, Rust provides utilities for this sort of use-cases e.g. unwrap_or
, map_or
, ...
Upvotes: 2