Skip to content

Commit 67b218e

Browse files
committed
Merge pull request #21109 from steveklabnik/gh17224
Provide example of generic inverse() Reviewed-by: alexcrichton
2 parents 8ec73df + ad0ce88 commit 67b218e

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/doc/trpl/generics.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ enum Result<H, N> {
8888
if we wanted to. Convention says that the first generic parameter should be
8989
`T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however.
9090

91-
The `Result<T, E>` type is intended to
92-
be used to return the result of a computation, and to have the ability to
93-
return an error if it didn't work out. Here's an example:
91+
The `Result<T, E>` type is intended to be used to return the result of a
92+
computation, and to have the ability to return an error if it didn't work out.
93+
Here's an example:
9494

9595
```{rust}
9696
let x: Result<f64, String> = Ok(2.3f64);

src/doc/trpl/traits.md

+73
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,76 @@ The names don't actually change to this, it's just for illustration. But
315315
as you can see, there's no overhead of deciding which version to call here,
316316
hence *statically dispatched*. The downside is that we have two copies of
317317
the same function, so our binary is a little bit larger.
318+
319+
## Our `inverse` Example
320+
321+
Back in [Generics](generics.html), we were trying to write code like this:
322+
323+
```{rust,ignore}
324+
fn inverse<T>(x: T) -> Result<T, String> {
325+
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
326+
327+
Ok(1.0 / x)
328+
}
329+
```
330+
331+
If we try to compile it, we get this error:
332+
333+
```text
334+
error: binary operation `==` cannot be applied to type `T`
335+
```
336+
337+
This is because `T` is too generic: we don't know if a random `T` can be
338+
compared. For that, we can use trait bounds. It doesn't quite work, but try
339+
this:
340+
341+
```{rust,ignore}
342+
fn inverse<T: PartialEq>(x: T) -> Result<T, String> {
343+
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
344+
345+
Ok(1.0 / x)
346+
}
347+
```
348+
349+
You should get this error:
350+
351+
```text
352+
error: mismatched types:
353+
expected `T`,
354+
found `_`
355+
(expected type parameter,
356+
found floating-point variable)
357+
```
358+
359+
So this won't work. While our `T` is `PartialEq`, we expected to have another `T`,
360+
but instead, we found a floating-point variable. We need a different bound. `Float`
361+
to the rescue:
362+
363+
```
364+
use std::num::Float;
365+
366+
fn inverse<T: Float>(x: T) -> Result<T, String> {
367+
if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
368+
369+
let one: T = Float::one();
370+
Ok(one / x)
371+
}
372+
```
373+
374+
We've had to replace our generic `0.0` and `1.0` with the appropriate methods
375+
from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function
376+
works just fine:
377+
378+
```
379+
# use std::num::Float;
380+
# fn inverse<T: Float>(x: T) -> Result<T, String> {
381+
# if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
382+
# let one: T = Float::one();
383+
# Ok(one / x)
384+
# }
385+
println!("the inverse of {} is {:?}", 2.0f32, inverse(2.0f32));
386+
println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64));
387+
388+
println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32));
389+
println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64));
390+
```

0 commit comments

Comments
 (0)