3

I'm trying to find and change a specific item in an iterator like this:

struct ItemType {
    name: &'static str,
    value: i32
}

struct OuterType {
    list: Vec<ItemType>
}

impl OuterType {
    pub fn setByName(
        self: &mut Self,
        name: &str
    ) -> Result<(), String> {

        match self.list.iter().find(|item| item.name == name) {
            Some(item_found) => {
                item_found.value = 1;
            },
            None => {
                return Err(format!("unrecognized item name (was \"{}\")", name));
            }
        }

        Ok(())
    }
}

But this does not compile because of several reasons, some of which:

  • no Copy trait (don't want to change a copy, I want to change the item in-place);
  • not borrowed, add & (does not help);
  • not mutable, add mut (does not help);
  • cannot assign to item_found.value which is behind a &;
  • at some point it says & can PROBABLY be removed... (WHAT?);
  • those errors are cyclic, I'm ping-pong-ing between them with no exit.

I've also tried to .find(|&item| ...).

What is going on? Don't I get to own the value returned by find()? And how am I supposed to change item_found.value? It's just an integer in a struct which is one of several in a vector I get the iterator for.

pid
  • 11,472
  • 6
  • 34
  • 63
  • What is the type of `iterator`? That's a very confusing set of errors you've got. At one point, you say it's not borrowed, and then two bullets down you tell us it's behind a `&`. Which is it? – Silvio Mayolo Oct 09 '21 at 15:55
  • What is `iterator`? Because *that* is what determines whether you can mutate a value or not – kmdreko Oct 09 '21 at 15:55
  • @SilvioMayolo as I change the code by following the error message hints I slip from one error to another. That's why there are different errors. In one version it says "not borrowed, add &", then it says "add mut", then "probably remove &" and so on... There's clearly an underlying problem I can't solve by just retouching code as indicated in error messages. – pid Oct 09 '21 at 15:58
  • @kmdreko I'll post a more complete version of the code in minute. – pid Oct 09 '21 at 15:59
  • 1
    Hint: `iter()` returns an immutable iterator. On the other hand, there is also `iter_mut()`. – SirDarius Oct 09 '21 at 16:12
  • Unrelated note, but you can do without a match entirely, thanks to a few tricks. See https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=714b105bfef33f4878978c5da7acc388 for a demonstration. – SirDarius Oct 09 '21 at 16:25
  • @SirDarius thanks I'll do it exactly that way! And..... the snake_case aaarghgh I'm struggling getting used to it! thanks for correcting that, too! – pid Oct 09 '21 at 16:31

1 Answers1

5

Just use iter_mut instead of iter when you need to mutate the value:

match self.list.iter_mut().find(...) {...}

Playground

Netwave
  • 40,134
  • 6
  • 50
  • 93
  • 1
    That actually worked! I'm rather impressed by rust about how painstakingly finicky it is! There's no way to fool it, but there's always a way to fool oneself :D – pid Oct 09 '21 at 16:26