From 964da1c9fd4ee0563cdcc7ff66cf60a3972127ee Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 26 Sep 2013 05:54:48 -0700 Subject: [PATCH 1/2] Document std::ops. Added an overview with a 'real' example, as well as toy implementations of all of the traits. Closes #9356. --- src/libstd/ops.rs | 412 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 410 insertions(+), 2 deletions(-) diff --git a/src/libstd/ops.rs b/src/libstd/ops.rs index 1d4d827434b..2f3e3eb9ca8 100644 --- a/src/libstd/ops.rs +++ b/src/libstd/ops.rs @@ -8,75 +8,483 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Traits for the built-in operators - +// So we don't have to document the actual methods on the traits. #[allow(missing_doc)]; +/*! + * + * Traits for the built-in operators. Implementing these traits allows you to get + * an effect similar to oveloading operators. + * + * The values for the right hand side of an operator are automatically + * borrowed, so `a + b` is sugar for `a.add(&b)`. + * + * # Example + * + * This example creates a `Point` struct that implements `Add` and `Sub`, and then + * demonstrates adding and subtracting two `Point`s. + * + * ```rust + * use std::ops::Add; + * use std::ops::Sub; + * + * struct Point { + * x: int, + * y: int + * } + * + * impl Add for Point { + * fn add(&self, other: &Point) -> Point { + * Point {x: self.x + other.x, y: self.y + other.y} + * } + * } + * + * impl Sub for Point { + * fn sub(&self, other: &Point) -> Point { + * Point {x: self.x - other.x, y: self.y - other.y} + * } + * } + * fn main() { + * println(format!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3})); + * println(format!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3})); + * } + * ``` + * + * See the documentation for each trait for a minimum implementation that prints + * something to the screen. + * + */ + +/** + * + * The `Drop` trait is used to run some code when a value goes out of scope. This + * is sometimes called a 'destructor'. + * + * # Example + * + * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes + * out of scope, and therefore `main` prints `Dropping!`. + * + * ```rust + * use std::ops::Drop; + * + * struct HasDrop; + * + * impl Drop for HasDrop { + * fn drop(&mut self) { + * println("Dropping!"); + * } + * } + * + * fn main() { + * let _x = HasDrop; + * } + * ``` + */ #[lang="drop"] pub trait Drop { fn drop(&mut self); } +/** + * + * The `Add` trait is used to override the functionality of `+`. + * + * # Example + * + * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up + * calling `add`, and therefore, `main` prints `Adding!`. + * + * ```rust + * use std::ops::Add; + * + * struct Foo; + * + * impl Add for Foo { + * fn add(&self, _rhs: &Foo) -> Foo { + * println("Adding!"); + * *self + * } + * } + * + * fn main() { + * Foo + Foo; + * } + * ``` + */ #[lang="add"] pub trait Add { fn add(&self, rhs: &RHS) -> Result; } +/** + * + * The `Sub` trait is used to override the functionality of `-`. + * + * # Example + * + * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up + * calling `sub`, and therefore, `main` prints `Subtracting!`. + * + * ``` + * use std::ops::Sub; + * + * struct Foo; + * + * impl Sub for Foo { + * fn sub(&self, _rhs: &Foo) -> Foo { + * println("Subtracting!"); + * *self + * } + * } + * + * fn main() { + * Foo - Foo; + * } + * ``` + */ #[lang="sub"] pub trait Sub { fn sub(&self, rhs: &RHS) -> Result; } +/** + * + * The `Mul` trait is used to override the functionality of `*`. + * + * # Example + * + * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up + * calling `mul`, and therefore, `main` prints `Multiplying!`. + * + * ```rust + * use std::ops::Mul; + * + * struct Foo; + * + * impl Mul for Foo { + * fn mul(&self, _rhs: &Foo) -> Foo { + * println("Multiplying!"); + * *self + * } + * } + * + * fn main() { + * Foo * Foo; + * } + * ``` + */ #[lang="mul"] pub trait Mul { fn mul(&self, rhs: &RHS) -> Result; } +/** + * + * The `Div` trait is used to override the functionality of `/`. + * + * # Example + * + * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up + * calling `div`, and therefore, `main` prints `Dividing!`. + * + * ``` + * use std::ops::Div; + * + * struct Foo; + * + * impl Div for Foo { + * fn div(&self, _rhs: &Foo) -> Foo { + * println("Dividing!"); + * *self + * } + * } + * + * fn main() { + * Foo / Foo; + * } + * ``` + */ #[lang="div"] pub trait Div { fn div(&self, rhs: &RHS) -> Result; } +/** + * + * The `Rem` trait is used to override the functionality of `%`. + * + * # Example + * + * A trivial implemtnation of `Rem`. When `Foo % Foo` happens, it ends up + * calling `rem`, and therefore, `main` prints `Remainder-ing!`. + * + * ``` + * use std::ops::Rem; + * + * struct Foo; + * + * impl Rem for Foo { + * fn rem(&self, _rhs: &Foo) -> Foo { + * println("Remainder-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo % Foo; + * } + * ``` + */ #[lang="rem"] pub trait Rem { fn rem(&self, rhs: &RHS) -> Result; } +/** + * + * The `Neg` trait is used to override the functionality of unary `-`. + * + * # Example + * + * A trivial implemtnation of `Neg`. When `-Foo` happens, it ends up calling + * `neg`, and therefore, `main` prints `Negating!`. + * + * ``` + * use std::ops::Neg; + * + * struct Foo; + * + * impl Neg for Foo { + * fn neg(&self) -> Foo { + * println("Negating!"); + * *self + * } + * } + * + * fn main() { + * -Foo; + * } + * ``` + */ #[lang="neg"] pub trait Neg { fn neg(&self) -> Result; } +/** + * + * The `Not` trait is used to override the functionality of `!`. + * + * # Example + * + * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling + * `not`, and therefore, `main` prints `Not-ing!`. + * + * ``` + * use std::ops::Not; + * + * struct Foo; + * + * impl Not for Foo { + * fn not(&self) -> Foo { + * println("Not-ing!"); + * *self + * } + * } + * + * fn main() { + * !Foo; + * } + * ``` + */ #[lang="not"] pub trait Not { fn not(&self) -> Result; } +/** + * + * The `BitAnd` trait is used to override the functionality of `&`. + * + * # Example + * + * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up + * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. + * + * ``` + * use std::ops::BitAnd; + * + * struct Foo; + * + * impl BitAnd for Foo { + * fn bitand(&self, _rhs: &Foo) -> Foo { + * println("Bitwise And-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo & Foo; + * } + * ``` + */ #[lang="bitand"] pub trait BitAnd { fn bitand(&self, rhs: &RHS) -> Result; } +/** + * + * The `BitOr` trait is used to override the functionality of `|`. + * + * # Example + * + * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up + * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. + * + * ``` + * use std::ops::BitOr; + * + * struct Foo; + * + * impl BitOr for Foo { + * fn bitor(&self, _rhs: &Foo) -> Foo { + * println("Bitwise Or-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo | Foo; + * } + * ``` + */ #[lang="bitor"] pub trait BitOr { fn bitor(&self, rhs: &RHS) -> Result; } +/** + * + * The `BitXor` trait is used to override the functionality of `^`. + * + * # Example + * + * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up + * calling `bixtor`, and therefore, `main` prints `Bitwise Xor-ing!`. + * + * ``` + * use std::ops::BitXor; + * + * struct Foo; + * + * impl BitXor for Foo { + * fn bitxor(&self, _rhs: &Foo) -> Foo { + * println("Bitwise Xor-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo ^ Foo; + * } + * ``` + */ #[lang="bitxor"] pub trait BitXor { fn bitxor(&self, rhs: &RHS) -> Result; } +/** + * + * The `Shl` trait is used to override the functionality of `<<`. + * + * # Example + * + * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up + * calling `shl`, and therefore, `main` prints `Shifting left!`. + * + * ``` + * use std::ops::Shl; + * + * struct Foo; + * + * impl Shl for Foo { + * fn shl(&self, _rhs: &Foo) -> Foo { + * println("Shifting left!"); + * *self + * } + * } + * + * fn main() { + * Foo << Foo; + * } + * ``` + */ #[lang="shl"] pub trait Shl { fn shl(&self, rhs: &RHS) -> Result; } +/** + * + * The `Shr` trait is used to override the functionality of `>>`. + * + * # Example + * + * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up + * calling `shr`, and therefore, `main` prints `Shifting right!`. + * + * ``` + * use std::ops::Shr; + * + * struct Foo; + * + * impl Shr for Foo { + * fn shr(&self, _rhs: &Foo) -> Foo { + * println("Shifting right!"); + * *self + * } + * } + * + * fn main() { + * Foo >> Foo; + * } + * ``` + */ #[lang="shr"] pub trait Shr { fn shr(&self, rhs: &RHS) -> Result; } +/** + * + * The `Index` trait is used to override the functionality of indexing operations + * like `arr[idx]`. + * + * # Example + * + * A trivial implementation of `Index`. When `Foo[idx]` happens, it ends up + * calling `index`, and therefore, `main` prints `Indexing!`. + * + * ``` + * use std::ops::Index; + * + * struct Foo; + * + * impl Index for Foo { + * fn index(&self, _rhs: &Foo) -> Foo { + * println("Indexing!"); + * *self + * } + * } + * + * fn main() { + * Foo[Foo]; + * } + * ``` + */ #[lang="index"] pub trait Index { fn index(&self, index: &Index) -> Result; From 28e88b4c6f752203c4ceff7d87094de63e8fdb8d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 27 Sep 2013 09:57:52 -0700 Subject: [PATCH 2/2] Update std::ops docs as per feedback from @chris-morgan --- src/libstd/ops.rs | 252 +++++++++++++++++++++------------------------- 1 file changed, 112 insertions(+), 140 deletions(-) diff --git a/src/libstd/ops.rs b/src/libstd/ops.rs index 2f3e3eb9ca8..3418fd939bd 100644 --- a/src/libstd/ops.rs +++ b/src/libstd/ops.rs @@ -15,30 +15,30 @@ * * Traits for the built-in operators. Implementing these traits allows you to get * an effect similar to oveloading operators. - * + * * The values for the right hand side of an operator are automatically * borrowed, so `a + b` is sugar for `a.add(&b)`. - * + * + * All of these traits are imported by the prelude, so they are available in + * every Rust program. + * * # Example - * + * * This example creates a `Point` struct that implements `Add` and `Sub`, and then * demonstrates adding and subtracting two `Point`s. - * + * * ```rust - * use std::ops::Add; - * use std::ops::Sub; - * * struct Point { * x: int, * y: int * } - * + * * impl Add for Point { * fn add(&self, other: &Point) -> Point { * Point {x: self.x + other.x, y: self.y + other.y} * } * } - * + * * impl Sub for Point { * fn sub(&self, other: &Point) -> Point { * Point {x: self.x - other.x, y: self.y - other.y} @@ -49,33 +49,31 @@ * println(format!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3})); * } * ``` - * + * * See the documentation for each trait for a minimum implementation that prints * something to the screen. - * + * */ /** - * + * * The `Drop` trait is used to run some code when a value goes out of scope. This * is sometimes called a 'destructor'. - * + * * # Example - * + * * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes * out of scope, and therefore `main` prints `Dropping!`. - * + * * ```rust - * use std::ops::Drop; - * * struct HasDrop; - * + * * impl Drop for HasDrop { * fn drop(&mut self) { * println("Dropping!"); * } * } - * + * * fn main() { * let _x = HasDrop; * } @@ -87,26 +85,24 @@ pub trait Drop { } /** - * - * The `Add` trait is used to override the functionality of `+`. - * + * + * The `Add` trait is used to specify the functionality of `+`. + * * # Example - * + * * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up * calling `add`, and therefore, `main` prints `Adding!`. - * + * * ```rust - * use std::ops::Add; - * * struct Foo; - * + * * impl Add for Foo { * fn add(&self, _rhs: &Foo) -> Foo { * println("Adding!"); * *self * } * } - * + * * fn main() { * Foo + Foo; * } @@ -118,26 +114,24 @@ pub trait Add { } /** - * - * The `Sub` trait is used to override the functionality of `-`. - * + * + * The `Sub` trait is used to specify the functionality of `-`. + * * # Example - * + * * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up * calling `sub`, and therefore, `main` prints `Subtracting!`. - * - * ``` - * use std::ops::Sub; - * + * + * ```rust * struct Foo; - * + * * impl Sub for Foo { * fn sub(&self, _rhs: &Foo) -> Foo { * println("Subtracting!"); * *self * } * } - * + * * fn main() { * Foo - Foo; * } @@ -149,26 +143,24 @@ pub trait Sub { } /** - * - * The `Mul` trait is used to override the functionality of `*`. - * + * + * The `Mul` trait is used to specify the functionality of `*`. + * * # Example - * + * * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up * calling `mul`, and therefore, `main` prints `Multiplying!`. - * + * * ```rust - * use std::ops::Mul; - * * struct Foo; - * + * * impl Mul for Foo { * fn mul(&self, _rhs: &Foo) -> Foo { * println("Multiplying!"); * *self * } * } - * + * * fn main() { * Foo * Foo; * } @@ -180,26 +172,24 @@ pub trait Mul { } /** - * - * The `Div` trait is used to override the functionality of `/`. - * + * + * The `Div` trait is used to specify the functionality of `/`. + * * # Example - * + * * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up * calling `div`, and therefore, `main` prints `Dividing!`. - * + * * ``` - * use std::ops::Div; - * * struct Foo; - * + * * impl Div for Foo { * fn div(&self, _rhs: &Foo) -> Foo { * println("Dividing!"); * *self * } * } - * + * * fn main() { * Foo / Foo; * } @@ -211,26 +201,24 @@ pub trait Div { } /** - * - * The `Rem` trait is used to override the functionality of `%`. - * + * + * The `Rem` trait is used to specify the functionality of `%`. + * * # Example - * - * A trivial implemtnation of `Rem`. When `Foo % Foo` happens, it ends up + * + * A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up * calling `rem`, and therefore, `main` prints `Remainder-ing!`. - * + * * ``` - * use std::ops::Rem; - * * struct Foo; - * + * * impl Rem for Foo { * fn rem(&self, _rhs: &Foo) -> Foo { * println("Remainder-ing!"); * *self * } * } - * + * * fn main() { * Foo % Foo; * } @@ -242,26 +230,24 @@ pub trait Rem { } /** - * - * The `Neg` trait is used to override the functionality of unary `-`. - * + * + * The `Neg` trait is used to specify the functionality of unary `-`. + * * # Example - * - * A trivial implemtnation of `Neg`. When `-Foo` happens, it ends up calling + * + * A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling * `neg`, and therefore, `main` prints `Negating!`. - * + * * ``` - * use std::ops::Neg; - * * struct Foo; - * + * * impl Neg for Foo { * fn neg(&self) -> Foo { * println("Negating!"); * *self * } * } - * + * * fn main() { * -Foo; * } @@ -273,26 +259,24 @@ pub trait Neg { } /** - * - * The `Not` trait is used to override the functionality of `!`. - * + * + * The `Not` trait is used to specify the functionality of unary `!`. + * * # Example - * + * * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling * `not`, and therefore, `main` prints `Not-ing!`. - * + * * ``` - * use std::ops::Not; - * * struct Foo; - * + * * impl Not for Foo { * fn not(&self) -> Foo { * println("Not-ing!"); * *self * } * } - * + * * fn main() { * !Foo; * } @@ -304,26 +288,24 @@ pub trait Not { } /** - * - * The `BitAnd` trait is used to override the functionality of `&`. - * + * + * The `BitAnd` trait is used to specify the functionality of `&`. + * * # Example - * + * * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. - * + * * ``` - * use std::ops::BitAnd; - * * struct Foo; - * + * * impl BitAnd for Foo { * fn bitand(&self, _rhs: &Foo) -> Foo { * println("Bitwise And-ing!"); * *self * } * } - * + * * fn main() { * Foo & Foo; * } @@ -335,26 +317,24 @@ pub trait BitAnd { } /** - * - * The `BitOr` trait is used to override the functionality of `|`. - * + * + * The `BitOr` trait is used to specify the functionality of `|`. + * * # Example - * + * * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. - * + * * ``` - * use std::ops::BitOr; - * * struct Foo; - * + * * impl BitOr for Foo { * fn bitor(&self, _rhs: &Foo) -> Foo { * println("Bitwise Or-ing!"); * *self * } * } - * + * * fn main() { * Foo | Foo; * } @@ -366,26 +346,24 @@ pub trait BitOr { } /** - * - * The `BitXor` trait is used to override the functionality of `^`. - * + * + * The `BitXor` trait is used to specify the functionality of `^`. + * * # Example - * + * * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up * calling `bixtor`, and therefore, `main` prints `Bitwise Xor-ing!`. - * + * * ``` - * use std::ops::BitXor; - * * struct Foo; - * + * * impl BitXor for Foo { * fn bitxor(&self, _rhs: &Foo) -> Foo { * println("Bitwise Xor-ing!"); * *self * } * } - * + * * fn main() { * Foo ^ Foo; * } @@ -397,26 +375,24 @@ pub trait BitXor { } /** - * - * The `Shl` trait is used to override the functionality of `<<`. - * + * + * The `Shl` trait is used to specify the functionality of `<<`. + * * # Example - * + * * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up * calling `shl`, and therefore, `main` prints `Shifting left!`. - * + * * ``` - * use std::ops::Shl; - * * struct Foo; - * + * * impl Shl for Foo { * fn shl(&self, _rhs: &Foo) -> Foo { * println("Shifting left!"); * *self * } * } - * + * * fn main() { * Foo << Foo; * } @@ -428,26 +404,24 @@ pub trait Shl { } /** - * - * The `Shr` trait is used to override the functionality of `>>`. - * + * + * The `Shr` trait is used to specify the functionality of `>>`. + * * # Example - * + * * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up * calling `shr`, and therefore, `main` prints `Shifting right!`. - * + * * ``` - * use std::ops::Shr; - * * struct Foo; - * + * * impl Shr for Foo { * fn shr(&self, _rhs: &Foo) -> Foo { * println("Shifting right!"); * *self * } * } - * + * * fn main() { * Foo >> Foo; * } @@ -459,27 +433,25 @@ pub trait Shr { } /** - * - * The `Index` trait is used to override the functionality of indexing operations + * + * The `Index` trait is used to specify the functionality of indexing operations * like `arr[idx]`. - * + * * # Example - * - * A trivial implementation of `Index`. When `Foo[idx]` happens, it ends up + * + * A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up * calling `index`, and therefore, `main` prints `Indexing!`. - * + * * ``` - * use std::ops::Index; - * * struct Foo; - * + * * impl Index for Foo { * fn index(&self, _rhs: &Foo) -> Foo { * println("Indexing!"); * *self * } * } - * + * * fn main() { * Foo[Foo]; * }