How to fix "a value of type `&Vec<char>` cannot be built from an iterator over elements of type `char`"

pub struct Interpreter<'a> {
    it:&'a Vec<char>,
}

impl<'a> Interpreter<'a> {
    pub fn new(infix: &str) -> Self {
        let  m = infix.chars().into_iter().collect()
        Self { it: m }
    }
    pub fn interpret(&mut self, out: &mut String) {
        self.term(out);
        while let Some(&op) = self.next_char() {
            if op == '+' || op == '-' {
                self.term(out);
                out.push(op)
            } else {
                // panic!("Unexpected symbol '{}'", op)
            }
        }
    }
    fn next_char(&mut self) -> Option<&char> {
        let m = self.it.iter().next();
        self.it.remove(0);
        return m;
    }
    fn term(&mut self, out: &mut String) {
        match self.next_char() {
            Some(&ch) if ch.is_digit(10) => out.push(ch),
            Some(&ch) => panic!("Unexpected symbol '{}'", ch),
            None => panic!("Unexpected end of string"),
        }
        println! {">>>>>>{}", out}
    }
}

fn main() {
    let mut intr = Interpreter::new("2+3");
    let mut postfix = String::new();
    intr.interpret(&mut postfix);
    assert_eq!(postfix, "23+");
    // intr = Interpreter::new("1-2+3-4");
    // postfix.clear();
    // intr.interpret(&mut postfix);
    // assert_eq!(postfix, "12-3+4-");
}

error: Compiling helloworld v0.1.0 (/Users/wuls/Desktop/rust/helloworld)
error[E0277]: a value of type &Vec<char> cannot be built from an iterator over elements of type char
--> src/main.rs:601:32
|
601 | let m = infix.chars().collect();
| ^^^^^^^ value of type &Vec<char> cannot be built from std::iter::Iterator<Item=char>
|
= help: the trait FromIterator<char> is not implemented for &Vec<char>

error: aborting due to previous error

For more information about this error, try rustc --explain E0277.
error: could not compile helloworld

To have a &Vec<char>, you must have a Vec<char> somewhere else. It's impossible to "collect" into the reference, since reference doesn't store anything, it's only a view.

5 Likes

it can't work when i use "Vec"

| pub struct Interpreter<'a> {
| ^^ unused parameter
|
= help: consider removing 'a, referring to it in a field, or using a marker such as PhantomData

Perhaps remove the 'a as the compiler suggested?

2 Likes

I can’t lost ‘a
would you help me that make it run

Could you explain this point? After dropping the reference and all related lifetime annotations, the only remaining compile error is in the next_char (playground), and it is impossible to implement with the written semantics, since to return Option<&char> you have to, again, store somewhere this char.

Here’s some minimal change to the code to make it compile (and not panic) after removing the lifetime parameters:

pub struct Interpreter {
    it: Vec<char>,
}

impl Interpreter {
    pub fn new(infix: &str) -> Self {
        let  m = infix.chars().into_iter().collect();
        Self { it: m }
    }
    pub fn interpret(&mut self, out: &mut String) {
        self.term(out);
        while let Some(op) = self.next_char() {
            if op == '+' || op == '-' {
                self.term(out);
                out.push(op)
            } else {
                // panic!("Unexpected symbol '{}'", op)
            }
        }
    }
    fn next_char(&mut self) -> Option<char> {
        let m = self.it.iter().next().copied();
        if m.is_some() {
            self.it.remove(0);
        }
        return m;
    }
    fn term(&mut self, out: &mut String) {
        match self.next_char() {
            Some(ch) if ch.is_digit(10) => out.push(ch),
            Some(ch) => panic!("Unexpected symbol '{}'", ch),
            None => panic!("Unexpected end of string"),
        }
        println! {">>>>>>{}", out}
    }
}

fn main() {
    let mut intr = Interpreter::new("2+3");
    let mut postfix = String::new();
    intr.interpret(&mut postfix);
    assert_eq!(postfix, "23+");
    // intr = Interpreter::new("1-2+3-4");
    // postfix.clear();
    // intr.interpret(&mut postfix);
    // assert_eq!(postfix, "12-3+4-");
}

Rust Playground

Note that repeated calls to .remove(0) on a Vec is inefficient. Consider using e.g. a std::vec::IntoIter or a VecDeque instead.

Or you could keep the lifetime parameter and store the std::str::Chars iterator directly. (In any case, you’d have to have next_char return Option<char>, not Option<&char>.) In this case you’d need to relate the lifetime parameter to the lifetime of the original &str, as you can see in the signature of the Interpreter::new method below.

pub struct Interpreter<'a> {
    it: std::str::Chars<'a>,
}

impl<'a> Interpreter<'a> {
    pub fn new(infix: &'a str) -> Self {
        let  m = infix.chars();
        Self { it: m }
    }
    pub fn interpret(&mut self, out: &mut String) {
        self.term(out);
        while let Some(op) = self.next_char() {
            if op == '+' || op == '-' {
                self.term(out);
                out.push(op)
            } else {
                // panic!("Unexpected symbol '{}'", op)
            }
        }
    }
    fn next_char(&mut self) -> Option<char> {
        self.it.next()
    }
    fn term(&mut self, out: &mut String) {
        match self.next_char() {
            Some(ch) if ch.is_digit(10) => out.push(ch),
            Some(ch) => panic!("Unexpected symbol '{}'", ch),
            None => panic!("Unexpected end of string"),
        }
        println! {">>>>>>{}", out}
    }
}

fn main() {
    let mut intr = Interpreter::new("2+3");
    let mut postfix = String::new();
    intr.interpret(&mut postfix);
    assert_eq!(postfix, "23+");
    // intr = Interpreter::new("1-2+3-4");
    // postfix.clear();
    // intr.interpret(&mut postfix);
    // assert_eq!(postfix, "12-3+4-");
}

Rust Playground

3 Likes

What follows is a walk-through of how I identified one key change, and then mechanically followed logical compiler suggestions until everything worked. I hope it's useful.


I started with your original code block. I wasn't entirely clear where to start, but after looking at next_char, it really seems like you're just trying to iterate over code points in order. So I commented out everything except for the struct and new:

    pub fn new(infix: &str) -> Self {
        // Just store the iterator
        let  it = infix.chars();
        Self { it }
    }

This way, you're just storing the iterator directly. It does what you want already. This is the key change I mentioned.

I didn't bother to adjust the struct, because I knew the compiler would tell me about it anyway. And indeed, the compiler told me what type was expected and I applied the change:

use core::str::Chars;
pub struct Interpreter<'a> {
    it: Chars<'a>,
}

And then it suggested a lifetime on new which I also added:

    pub fn new(infix: &'a str) -> Self {

This compiled. Next we'll need to make everything else work with the change.


So next I updated next_char to match the iterator. The iterator returns chars, not references. So:

    fn next_char(&mut self) -> Option<char> {
        self.it.next()
    }

This compiled.

It wasn't entirely clear which method would be better to tackle next, so I picked term arbitrarily. The compiler just suggested I remove a couple references (that were now char, not &char), and I did so. That worked, so I moved on to interpret, and the same pattern followed.

That's all that was needed for all methods to compile.


All that left was main. I uncommented that too, and it all seems to work with no further changes.

1 Like

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.