-
Notifications
You must be signed in to change notification settings - Fork 1.5k
generics/phantom/testcase_units: alleviate the syntactical heaviness of the types and bounds #583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6e90656
e2ac5aa
a8c37f0
875e3af
6986e28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,21 +2,17 @@ A useful method of unit conversions can be examined by implementing `Add` | |
for a phantom type. The `Add` `trait` is examined below: | ||
|
||
```rust | ||
// This construction would impose: `Self + RHS = Output`. | ||
// This construction would impose: `Self + RHS = Output` | ||
// where RHS defaults to Self if not specified in the implementation. | ||
pub trait Add<RHS = Self> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't quite right. impl Add<f64> for T {} // T + f64 (override default)
impl Add for T // T + T (RHS is Self because of the default) There is no defaults section though probably because I couldn't figure them out when I was working on the associated types sections. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: this isn't your mistake. It just wasn't written correctly before. It's mainly an issue because it uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apologies, I missed that comment yesterday... Well I didn't know about that defaulting mechanism indeed, it's nice. |
||
type Output; | ||
|
||
fn add(self, rhs: RHS) -> Self::Output; | ||
} | ||
|
||
// So, `Output` must be `T` and therefore, `T + T = T`. | ||
impl<T> Add<T, Output = T> for T {} | ||
|
||
// Similarly, this imposes: `S<T> + S<T> = S<T>` can be | ||
// added only when `T + T = T`. | ||
impl<S<T>> Add<S<T> for S<T> where | ||
T: Add<T, Output = T> { | ||
type Output = S<T>; | ||
// `Output` must be `T<U>` so that `T<U> + T<U> = T<U>`. | ||
impl<U> Add for T<U> { | ||
type Output = T<U>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be inclined to drop one of these 2 blocks because that super heavyweight bounds section isn't there anymore however you as the reader have better insight than I do on whether these are helpful. Therefore deferring to your judgement seems the most proper thing to do. |
||
... | ||
} | ||
``` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,48 @@ | ||
use std::ops::Add; | ||
use std::marker::PhantomData; | ||
|
||
/// Null enumerations to define unit types | ||
/// Null enumerations define unit types. | ||
#[derive(Debug, Clone, Copy)] | ||
struct Inch; | ||
#[derive(Debug, Clone, Copy)] | ||
struct Mm; | ||
|
||
/// Length is phantom type with hidden parameter `Unit` | ||
/// `Length` is phantom type with hidden parameter `Unit`. | ||
/// | ||
/// `f64` already implements the `Clone` and `Copy` traits. | ||
#[derive(Debug, Clone, Copy)] | ||
struct Length<Unit, T>(T,PhantomData<Unit>); | ||
struct Length<Unit>(f64,PhantomData<Unit>); | ||
|
||
// This is similar to the header except `T` must also | ||
// implement `Clone` and `Copy. | ||
impl<Unit, T> Add<Length<Unit, T>> for Length<Unit, T> where | ||
T: Add<T, Output=T> + Clone + Copy { | ||
type Output = Length<Unit, T>; | ||
/// The `Add` trait defines the behavior of the `+` operator. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why you wanted a period added here and at line 20, since the rest of the website never uses periods in the playpens. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The official policy is that comments should be punctuated. Generally that's fairly easy to check in small patches but rbe has had many many sweeping changes in the past year where it's hard to notice little things like that. Ideally rbe would start conforming more to the standard. The situation should get better with time and stability. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mdinger yes, thanks you beat me to it, and i just mentioned it #583 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I should terminate the rest of the comments too ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you'd like, yes. Thanks :) |
||
impl<Unit> Add for Length<Unit> { | ||
type Output = Length<Unit>; | ||
|
||
fn add(self, r: Length<Unit, T>) -> Length<Unit, T> { | ||
Length(self.0 + r.0, PhantomData) | ||
// add() returns a new `Length` struct containing the sum. | ||
fn add(self, rhs: Length<Unit>) -> Length<Unit> { | ||
// `+` calls the `Add` implementation for `f64`. | ||
Length(self.0 + rhs.0, PhantomData) | ||
} | ||
} | ||
|
||
fn main() { | ||
// Specialize one_foot to have hidden parameter `Inch` | ||
let one_foot: Length<Inch, f32> = Length(12.0, PhantomData); | ||
// one_meter has hidden parameter `Mm` | ||
let one_meter: Length<Mm, f32> = Length(1000.0, PhantomData); | ||
|
||
// Specializes `one_foot` to have hidden parameter `Inch`. | ||
let one_foot: Length<Inch> = Length(12.0, PhantomData); | ||
// `one_meter` has hidden parameter `Mm`. | ||
let one_meter: Length<Mm> = Length(1000.0, PhantomData); | ||
|
||
// `+` calls the `add()` method we implemented for `Length<Unit>`. | ||
// | ||
// Since `Length` implements `Clone` + `Copy`, `add()` does not consume | ||
// `one_foot` and `one_meter` but makes a copy of them in `self` and `rhs`. | ||
let two_feet = one_foot + one_foot; | ||
let two_meters = one_meter + one_meter; | ||
|
||
// Addition works | ||
// Addition works. | ||
println!("one foot + one_foot = {:?}", two_feet); | ||
println!("one meter + one_meter = {:?}", two_meters); | ||
|
||
// Nonsensical operations fail as they should | ||
// Error: type mismatch | ||
// Nonsensical operations fail as they should: | ||
// Error: type mismatch. | ||
//let one_feter = one_foot + one_meter; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the period to the end of the sentence. I'm not sure if you wanted it removed completely, but I thought that would be inconsistent with line 13.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, we may have inconsistencies. Rust by Example was donated to the Rust organization, and I haven't had the chance to go over the entire thing yet. So, when adding new stuff, I tend to apply our already-existing conventions, even though the project as a whole may not have totally adopted them yet. Make sense?