Better way to do add number in array

I have this array.

let mut arr = [0u8; 4];

What I want is check the first zero and replace it given number. Currently I'm doing it like this.

arr.iter_mut().any(move |t| { if *t == 0 { *t = num; true } else { false }});

This looks kinda Hacky and ugly. Is there any other better way to write this?

You don't have to do everything with iterators:

for item in &mut arr {
   if *item == 0 {
       *item = num;
       break;
   }
}

but with iterators it could be:

arr.iter_mut().find(|i| **i == 0).map(|i| *i = num)
6 Likes

Thanks. I think second one look nicer

I never really liked the functional programming approach when you want to mutate the iterator, although I also do that, if my function is just one method chain and I'd have to add an extra statement to mutate.

Just ignore this and move on

The problem with the given solution is, that map does not execute by itself. You probably want .map_or((), |i| *i = num), instead, which is executed eagerly.

P.S.: You may have to write |i| { *i = num; }, instead. I'm unsure if *i = num is an expression that returns () or the value of *i.

That's actually Option::map, not Iterator::map (I thought the same thing at first glance, but find is the key)

2 Likes
Just ignore this and move on

Option::map is lazy, too. Nvm, you probably talked about my first paragraph. You're right. It's not really mutating the iterator, only a single value, for which a mutable reference is returned.

One of us is confused here.

1 Like

Oh, damn. You're right. I really got confused. You only need map_or for unwrapping. :man_facepalming:t3::heart:

IMO it's bad style to use a map function, even if it isn't lazy, without using the result because the function is semantically more than you need. So I would do:

if let Some(i) = arr.iter_mut().find(|i| **i == 0) {
  *i = num;
}
3 Likes