h_a
May 8, 2021, 2:42pm
1
I would like to create a trait method that works on &str
. Currently I am using free functions like this:
trait BitOp {
fn is_bitop(&self) -> bool;
fn not_bitop(&self) -> bool;
}
impl BitOp for &str {
fn is_bitop(&self) -> bool {
matches!(*self, "AND" | "OR" | "NOT" | "LSHIFT" | "RSHIFT" | "->")
}
fn not_bitop(&self) -> bool {
!self.is_bitop()
}
}
fn ops(arg: &str) -> impl Iterator<Item = &str> {
arg.split_ascii_whitespace().filter(BitOp::is_bitop)
}
fn idents(arg: &str) -> impl Iterator<Item = &str> {
arg.split_ascii_whitespace().filter(BitOp::not_bitop)
}
However free functions mean that I cannot use nice UFCS syntax that Rust has for traits. How should I implement these as traits for both String
and &str
so that the calls to them look like something like this: string.idents().iter()...
?
alice
May 8, 2021, 2:53pm
2
You gotta put it on the trait itself like you did with is_bitop
. Unfortunately you cannot use impl Trait
as the return type when doing this, so you will have to define a nameable type for the iterator. For example:
trait BitOp {
type OpsIter: Iterator<Item = Self>;
fn is_bitop(self) -> bool;
fn not_bitop(self) -> bool;
fn ops(self) -> Self::OpsIter;
}
impl<'a> BitOp for &'a str {
type OpsIter = MyOpsIter<'a>;
fn is_bitop(self) -> bool {
matches!(self, "AND" | "OR" | "NOT" | "LSHIFT" | "RSHIFT" | "->")
}
fn not_bitop(self) -> bool {
!self.is_bitop()
}
fn ops(self) -> MyOpsIter<'a> {
MyOpsIter {
inner: self.split_ascii_whitespace(),
}
}
}
struct MyOpsIter<'a> {
inner: std::str::SplitAsciiWhitespace<'a>,
}
impl<'a> Iterator for MyOpsIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
loop {
match self.inner.next() {
Some(value) if value.is_bitop() => return Some(value),
None => return None,
_ => continue,
}
}
}
}
system
Closed
August 6, 2021, 2:53pm
3
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.