How to create a trait method that returns an iterator

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()...?

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,
            }
        }
    }
}

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.