parent
e289b689d4
commit
1c48227b3c
@ -90,88 +90,3 @@ if we wanted to. Convention says that the first generic parameter should be
|
||||
|
||||
The `Result<T, E>` type is intended to be used to return the result of a
|
||||
computation, and to have the ability to return an error if it didn't work out.
|
||||
Here's an example:
|
||||
|
||||
```{rust}
|
||||
let x: Result<f64, String> = Ok(2.3f64);
|
||||
let y: Result<f64, String> = Err("There was an error.".to_string());
|
||||
```
|
||||
|
||||
This particular Result will return an `f64` if there's a success, and a
|
||||
`String` if there's a failure. Let's write a function that uses `Result<T, E>`:
|
||||
|
||||
```{rust}
|
||||
fn inverse(x: f64) -> Result<f64, String> {
|
||||
if x == 0.0f64 { return Err("x cannot be zero!".to_string()); }
|
||||
|
||||
Ok(1.0f64 / x)
|
||||
}
|
||||
```
|
||||
|
||||
We don't want to take the inverse of zero, so we check to make sure that we
|
||||
weren't passed zero. If we were, then we return an `Err`, with a message. If
|
||||
it's okay, we return an `Ok`, with the answer.
|
||||
|
||||
Why does this matter? Well, remember how `match` does exhaustive matches?
|
||||
Here's how this function gets used:
|
||||
|
||||
```{rust}
|
||||
# fn inverse(x: f64) -> Result<f64, String> {
|
||||
# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); }
|
||||
# Ok(1.0f64 / x)
|
||||
# }
|
||||
let x = inverse(25.0f64);
|
||||
|
||||
match x {
|
||||
Ok(x) => println!("The inverse of 25 is {}", x),
|
||||
Err(msg) => println!("Error: {}", msg),
|
||||
}
|
||||
```
|
||||
|
||||
The `match` enforces that we handle the `Err` case. In addition, because the
|
||||
answer is wrapped up in an `Ok`, we can't just use the result without doing
|
||||
the match:
|
||||
|
||||
```{rust,ignore}
|
||||
let x = inverse(25.0f64);
|
||||
println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied
|
||||
// to type `core::result::Result<f64,collections::string::String>`
|
||||
```
|
||||
|
||||
This function is great, but there's one other problem: it only works for 64 bit
|
||||
floating point values. What if we wanted to handle 32 bit floating point as
|
||||
well? We'd have to write this:
|
||||
|
||||
```{rust}
|
||||
fn inverse32(x: f32) -> Result<f32, String> {
|
||||
if x == 0.0f32 { return Err("x cannot be zero!".to_string()); }
|
||||
|
||||
Ok(1.0f32 / x)
|
||||
}
|
||||
```
|
||||
|
||||
Bummer. What we need is a *generic function*. Luckily, we can write one!
|
||||
However, it won't _quite_ work yet. Before we get into that, let's talk syntax.
|
||||
A generic version of `inverse` would look something like this:
|
||||
|
||||
```{rust,ignore}
|
||||
fn inverse<T>(x: T) -> Result<T, String> {
|
||||
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
|
||||
|
||||
Ok(1.0 / x)
|
||||
}
|
||||
```
|
||||
|
||||
Just like how we had `Option<T>`, we use a similar syntax for `inverse<T>`.
|
||||
We can then use `T` inside the rest of the signature: `x` has type `T`, and half
|
||||
of the `Result` has type `T`. However, if we try to compile that example, we'll get
|
||||
an error:
|
||||
|
||||
```text
|
||||
error: binary operation `==` cannot be applied to type `T`
|
||||
```
|
||||
|
||||
Because `T` can be _any_ type, it may be a type that doesn't implement `==`,
|
||||
and therefore, the first line would be wrong. What do we do?
|
||||
|
||||
To fix this example, we need to learn about another Rust feature: traits.
|
||||
|
Loading…
x
Reference in New Issue
Block a user