In this code found at https://doc.rust-lang.org/std/ops/trait.BitAnd.html:
use std::ops::BitAnd;
#[derive(Debug, PartialEq)]
struct BooleanVector(Vec<bool>);
impl BitAnd for BooleanVector {
type Output = Self;
fn bitand(self, Self(rhs): Self) -> Self::Output {
let Self(lhs) = self;
assert_eq!(lhs.len(), rhs.len());
Self(
lhs.iter()
.zip(rhs.iter())
.map(|(x, y)| *x & *y)
.collect()
)
}
}
let bv1 = BooleanVector(vec![true, true, false, false]);
let bv2 = BooleanVector(vec![true, false, true, false]);
let expected = BooleanVector(vec![true, false, false, false]);
assert_eq!(bv1 & bv2, expected);
What is Self(rhs) and Self(lhs)?
Where does rhs and lhs come from?
What is
Self(rhs)andSelf(lhs)?Where does rhs and lhs come from?
They're patterns. Rust patterns can be faillible, which is how they're generally used (e.g. in match, or if let). But they can also be infaillible.
A basic let, or for, takes an infaillible pattern as left-hand side. Aside from a trivial binding, this is most commonly encountered with a tuple:
let (a, b, c) = ...;
(a, b, c) is a tuple-pattern, and gets pattern-matched and "unpacked".
This also works with structs in general, and here tuple structs. So
let Self(lhs) = self;
is just a pattern, which does the reverse operation as
let self = Self(lhs);
Same with using a pattern as left-hand side in a parameter declaration.
So lhs and rhs come from pattern-matching the two parameters of the method.
For more, see the book: https://doc.rust-lang.org/book/ch18-01-all-the-places-for-patterns.html#let-statements
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With